Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 15219791 | 816 days ago | IN | 0 ETH | 0.12232359 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
VPool
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/contracts/proxy/utils/Initializable.sol"; import "../dependencies/openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../dependencies/openzeppelin/contracts/security/ReentrancyGuard.sol"; import "./PoolERC20Permit.sol"; import "./PoolStorage.sol"; import "../Errors.sol"; import "../Governable.sol"; import "../Pausable.sol"; import "../interfaces/vesper/IPoolAccountant.sol"; import "../interfaces/vesper/IPoolRewards.sol"; import "vesper-commons/contracts/interfaces/vesper/IStrategy.sol"; /// @title Holding pool share token // solhint-disable no-empty-blocks contract VPool is Initializable, PoolERC20Permit, Governable, Pausable, ReentrancyGuard, PoolStorageV3 { using SafeERC20 for IERC20; using EnumerableSet for EnumerableSet.AddressSet; string public constant VERSION = "5.0.2"; uint256 public constant MAX_BPS = 10_000; // For simplicity we are assuming 365 days as 1 year uint256 public constant ONE_YEAR = 365 days; event UpdatedMaximumProfitAsFee(uint256 oldMaxProfitAsFee, uint256 newMaxProfitAsFee); event UpdatedMinimumDepositLimit(uint256 oldDepositLimit, uint256 newDepositLimit); event Deposit(address indexed owner, uint256 shares, uint256 amount); event Withdraw(address indexed owner, uint256 shares, uint256 amount); event UpdatedUniversalFee(uint256 oldUniversalFee, uint256 newUniversalFee); event UpdatedPoolRewards(address indexed previousPoolRewards, address indexed newPoolRewards); event UpdatedWithdrawFee(uint256 previousWithdrawFee, uint256 newWithdrawFee); event UniversalFeePaid(uint256 strategyDebt, uint256 profit, uint256 fee); // We are using constructor to initialize implementation with basic details constructor( string memory _name, string memory _symbol, address _token ) PoolERC20(_name, _symbol) { // 0x0 is acceptable as has no effect on functionality token = IERC20(_token); } /// @dev Equivalent to constructor for proxy. It can be called only once per proxy. function initialize( string memory _name, string memory _symbol, address _token, address _poolAccountant ) public initializer { require(_token != address(0), Errors.INPUT_ADDRESS_IS_ZERO); require(_poolAccountant != address(0), Errors.INPUT_ADDRESS_IS_ZERO); __ERC20_init(_name, _symbol); __ERC20Permit_init(_name); __Governable_init(); token = IERC20(_token); require(_keepers.add(_msgSender()), Errors.ADD_IN_LIST_FAILED); require(_maintainers.add(_msgSender()), Errors.ADD_IN_LIST_FAILED); poolAccountant = _poolAccountant; universalFee = 200; // 2% maxProfitAsFee = 5_000; // 50% minDepositLimit = 1; } modifier onlyKeeper() { require(governor == _msgSender() || _keepers.contains(_msgSender()), "not-a-keeper"); _; } modifier onlyMaintainer() { require(governor == _msgSender() || _maintainers.contains(_msgSender()), "not-a-maintainer"); _; } /** * @notice Deposit ERC20 tokens and receive pool shares depending on the current share price. * @param _amount ERC20 token amount. */ function deposit(uint256 _amount) external nonReentrant whenNotPaused { _updateRewards(_msgSender()); _deposit(_amount); } /** * @notice Deposit ERC20 tokens and claim rewards if any * @param _amount ERC20 token amount. */ function depositAndClaim(uint256 _amount) external nonReentrant whenNotPaused { _depositAndClaim(_amount); } /** * @notice Deposit ERC20 tokens with permit aka gasless approval. * @param _amount ERC20 token amount. * @param _deadline The time at which signature will expire * @param _v The recovery byte of the signature * @param _r Half of the ECDSA signature pair * @param _s Half of the ECDSA signature pair */ function depositWithPermit( uint256 _amount, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external nonReentrant whenNotPaused { IERC20Permit(address(token)).permit(_msgSender(), address(this), _amount, _deadline, _v, _r, _s); _updateRewards(_msgSender()); _deposit(_amount); } /** * @notice Withdraw collateral based on given shares and the current share price. * Burn remaining shares and return collateral. Claim rewards if there is any * @dev Deprecated method. Keeping this method here for backward compatibility. * @param _shares Pool shares. It will be in 18 decimals. */ function whitelistedWithdraw(uint256 _shares) external nonReentrant whenNotShutdown { _claimRewards(_msgSender()); _withdraw(_shares); } /** * @notice Withdraw collateral based on given shares and the current share price. * Burn remaining shares and return collateral. * @param _shares Pool shares. It will be in 18 decimals. */ function withdraw(uint256 _shares) external nonReentrant whenNotShutdown { _updateRewards(_msgSender()); _withdraw(_shares); } /** * @notice Withdraw collateral and claim rewards if any * @param _shares Pool shares. It will be in 18 decimals. */ function withdrawAndClaim(uint256 _shares) external nonReentrant whenNotShutdown { _withdrawAndClaim(_shares); } /** * @notice Transfer tokens to multiple recipient * @dev Address array and amount array are 1:1 and are in order. * @param _recipients array of recipient addresses * @param _amounts array of token amounts * @return true/false */ function multiTransfer(address[] calldata _recipients, uint256[] calldata _amounts) external returns (bool) { require(_recipients.length == _amounts.length, Errors.INPUT_LENGTH_MISMATCH); for (uint256 i = 0; i < _recipients.length; i++) { require(transfer(_recipients[i], _amounts[i]), Errors.MULTI_TRANSFER_FAILED); } return true; } /** * @notice Strategy call this in regular interval. Only strategy function. * @param _profit yield generated by strategy. Strategy get performance fee on this amount * @param _loss Reduce debt ,also reduce debtRatio, increase loss in record. * @param _payback strategy willing to payback outstanding above debtLimit. no performance fee on this amount. * when governance has reduced debtRatio of strategy, strategy will report profit and payback amount separately. */ function reportEarning( uint256 _profit, uint256 _loss, uint256 _payback ) external { address _strategy = _msgSender(); // Calculate universal fee if (_profit > 0) { (, , , uint256 _lastRebalanceAt, uint256 _totalDebt, , , , ) = IPoolAccountant(poolAccountant).strategy(_strategy); uint256 _fee = _calculateUniversalFee(_lastRebalanceAt, _totalDebt, _profit); // Mint shares equal to universal fee if (_fee > 0) { _mint(IStrategy(_strategy).feeCollector(), _calculateShares(_fee)); emit UniversalFeePaid(_totalDebt, _profit, _fee); } } // Report earning in pool accountant (uint256 _actualPayback, uint256 _creditLine) = IPoolAccountant(poolAccountant).reportEarning(_strategy, _profit, _loss, _payback); uint256 _totalPayback = _profit + _actualPayback; // After payback, if strategy has credit line available then send more fund to strategy // If payback is more than available credit line then get fund from strategy if (_totalPayback < _creditLine) { token.safeTransfer(_strategy, _creditLine - _totalPayback); } else if (_totalPayback > _creditLine) { token.safeTransferFrom(_strategy, address(this), _totalPayback - _creditLine); } } /** * @notice Report loss outside of rebalance activity. * @dev Some strategies pay deposit fee thus realizing loss at deposit. * For example: Curve's 3pool has some slippage due to deposit of one asset in 3pool. * Strategy may want report this loss instead of waiting for next rebalance. * @param _loss Loss that strategy want to report */ function reportLoss(uint256 _loss) external { if (_loss > 0) { IPoolAccountant(poolAccountant).reportLoss(_msgSender(), _loss); } } /** * @dev Transfer given ERC20 token to governor * @param _fromToken Token address to sweep */ function sweepERC20(address _fromToken) external onlyKeeper { require(_fromToken != address(token), Errors.NOT_ALLOWED_TO_SWEEP); IERC20(_fromToken).safeTransfer(governor, IERC20(_fromToken).balanceOf(address(this))); } /** * @notice Get available credit limit of strategy. This is the amount strategy can borrow from pool * @dev Available credit limit is calculated based on current debt of pool and strategy, current debt limit of pool and strategy. * credit available = min(pool's debt limit, strategy's debt limit, max debt per rebalance) * when some strategy do not pay back outstanding debt, this impact credit line of other strategy if totalDebt of pool >= debtLimit of pool * @param _strategy Strategy address */ function availableCreditLimit(address _strategy) external view returns (uint256) { return IPoolAccountant(poolAccountant).availableCreditLimit(_strategy); } /** * @notice Calculate universal fee for calling strategy. This is only strategy function. * @dev Earn strategies will call this during rebalance. */ function calculateUniversalFee(uint256 _profit) external view returns (uint256 _fee) { return _calculateUniversalFee(_msgSender(), _profit); } /** * @notice Debt above current debt limit * @param _strategy Address of strategy */ function excessDebt(address _strategy) external view returns (uint256) { return IPoolAccountant(poolAccountant).excessDebt(_strategy); } function getStrategies() external view returns (address[] memory) { return IPoolAccountant(poolAccountant).getStrategies(); } /// @notice Get total debt of pool function totalDebt() external view returns (uint256) { return IPoolAccountant(poolAccountant).totalDebt(); } /** * @notice Get total debt of given strategy * @param _strategy Strategy address */ function totalDebtOf(address _strategy) external view returns (uint256) { return IPoolAccountant(poolAccountant).totalDebtOf(_strategy); } /// @notice Get total debt ratio. Total debt ratio helps us keep buffer in pool function totalDebtRatio() external view returns (uint256) { return IPoolAccountant(poolAccountant).totalDebtRatio(); } /** * @notice Calculate how much shares user will get for given amount. Also return externalDepositFee if any. * @param _amount Collateral amount * @return _shares Amount of share that user will get * @dev Amount should be >= minimum deposit limit which default to 1 */ function calculateMintage(uint256 _amount) public view returns (uint256 _shares) { require(_amount >= minDepositLimit, Errors.INVALID_COLLATERAL_AMOUNT); uint256 _externalDepositFee = (_amount * IPoolAccountant(poolAccountant).externalDepositFee()) / MAX_BPS; _shares = _calculateShares(_amount - _externalDepositFee); } function getWithdrawQueue() public view returns (address[] memory) { return IPoolAccountant(poolAccountant).getWithdrawQueue(); } /** * @notice Get price per share * @dev Return value will be in token defined decimals. */ function pricePerShare() public view returns (uint256) { if (totalSupply() == 0 || totalValue() == 0) { return 10**IERC20Metadata(address(token)).decimals(); } return (totalValue() * 1e18) / totalSupply(); } function strategy(address _strategy) public view returns ( bool _active, uint256 _interestFee, // Obsolete uint256 _debtRate, // Obsolete uint256 _lastRebalance, uint256 _totalDebt, uint256 _totalLoss, uint256 _totalProfit, uint256 _debtRatio, uint256 _externalDepositFee ) { return IPoolAccountant(poolAccountant).strategy(_strategy); } /// @dev Returns the token stored in the pool. It will be in token defined decimals. function tokensHere() public view returns (uint256) { return token.balanceOf(address(this)); } /** * @notice Returns sum of token locked in other contracts and token stored in the pool. * It will be in token defined decimals. */ function totalValue() public view returns (uint256) { return IPoolAccountant(poolAccountant).totalDebt() + tokensHere(); } /** * @dev Hook that is called just after burning tokens. * @param _amount Collateral amount in collateral token defined decimals. */ function _afterBurning(uint256 _amount) internal virtual returns (uint256) { token.safeTransfer(_msgSender(), _amount); return _amount; } /// @notice claim rewards of account function _claimRewards(address _account) internal { if (poolRewards != address(0)) { IPoolRewards(poolRewards).claimReward(_account); } } /// @dev Deposit incoming token and mint pool token i.e. shares. function _deposit(uint256 _amount) internal { uint256 _shares = calculateMintage(_amount); token.safeTransferFrom(_msgSender(), address(this), _amount); _mint(_msgSender(), _shares); emit Deposit(_msgSender(), _shares, _amount); } /// @dev Deposit token and claim rewards if any function _depositAndClaim(uint256 _amount) internal { _claimRewards(_msgSender()); _deposit(_amount); } /// @dev Update pool rewards of sender and receiver during transfer. function _transfer( address sender, address recipient, uint256 amount ) internal override { if (poolRewards != address(0)) { IPoolRewards(poolRewards).updateReward(sender); IPoolRewards(poolRewards).updateReward(recipient); } super._transfer(sender, recipient, amount); } function _updateRewards(address _account) internal { if (poolRewards != address(0)) { IPoolRewards(poolRewards).updateReward(_account); } } /// @dev Burns shares and returns the collateral value, after fee, of those. function _withdraw(uint256 _shares) internal { require(_shares > 0, Errors.INVALID_SHARE_AMOUNT); (uint256 _amountWithdrawn, bool _isPartial) = _beforeBurning(_shares); // There may be scenarios when pool is not able to withdraw all of requested amount if (_isPartial) { // Recalculate proportional share on actual amount withdrawn uint256 _proportionalShares = _calculateShares(_amountWithdrawn); if (_proportionalShares < _shares) { _shares = _proportionalShares; } } _burn(_msgSender(), _shares); _afterBurning(_amountWithdrawn); emit Withdraw(_msgSender(), _shares, _amountWithdrawn); } /// @dev Withdraw collateral and claim rewards if any function _withdrawAndClaim(uint256 _shares) internal { _claimRewards(_msgSender()); _withdraw(_shares); } function _withdrawCollateral(uint256 _amount) internal { // Withdraw amount from queue uint256 _debt; uint256 _balanceAfter; uint256 _balanceBefore; uint256 _amountWithdrawn; uint256 _totalAmountWithdrawn; address[] memory _withdrawQueue = getWithdrawQueue(); uint256 _len = _withdrawQueue.length; for (uint256 i; i < _len; i++) { uint256 _amountNeeded = _amount - _totalAmountWithdrawn; address _strategy = _withdrawQueue[i]; _debt = IPoolAccountant(poolAccountant).totalDebtOf(_strategy); if (_debt == 0) { continue; } if (_amountNeeded > _debt) { // Should not withdraw more than current debt of strategy. _amountNeeded = _debt; } _balanceBefore = tokensHere(); //solhint-disable no-empty-blocks try IStrategy(_strategy).withdraw(_amountNeeded) {} catch { continue; } _balanceAfter = tokensHere(); _amountWithdrawn = _balanceAfter - _balanceBefore; // Adjusting totalDebt. Assuming that during next reportEarning(), strategy will report loss if amountWithdrawn < _amountNeeded IPoolAccountant(poolAccountant).decreaseDebt(_strategy, _amountWithdrawn); _totalAmountWithdrawn += _amountWithdrawn; if (_totalAmountWithdrawn >= _amount) { // withdraw done break; } } } /** * @dev Before burning hook. * withdraw amount from strategies */ function _beforeBurning(uint256 _share) private returns (uint256 _actualWithdrawn, bool _isPartial) { uint256 _amount = (_share * pricePerShare()) / 1e18; uint256 _tokensHere = tokensHere(); _actualWithdrawn = _amount; // Check for partial withdraw scenario // If we do not have enough tokens then withdraw whats needed from strategy if (_amount > _tokensHere) { // Strategy may withdraw partial _withdrawCollateral(_amount - _tokensHere); _tokensHere = tokensHere(); if (_amount > _tokensHere) { _actualWithdrawn = _tokensHere; _isPartial = true; } } require(_actualWithdrawn > 0, Errors.INVALID_COLLATERAL_AMOUNT); } /** * @dev Calculate shares to mint/burn based on the current share price and given amount. * @param _amount Collateral amount in collateral token defined decimals. * @return share amount in 18 decimal */ function _calculateShares(uint256 _amount) private view returns (uint256) { uint256 _share = ((_amount * 1e18) / pricePerShare()); return _amount > ((_share * pricePerShare()) / 1e18) ? _share + 1 : _share; } /** * @dev Calculate universal fee based on strategy's TVL, profit earned and duration between rebalance and now. */ function _calculateUniversalFee(address _strategy, uint256 _profit) private view returns (uint256 _fee) { // Calculate universal fee (, , , uint256 _lastRebalance, uint256 _totalDebt, , , , ) = IPoolAccountant(poolAccountant).strategy(_strategy); return _calculateUniversalFee(_lastRebalance, _totalDebt, _profit); } function _calculateUniversalFee( uint256 _lastRebalance, uint256 _totalDebt, uint256 _profit ) private view returns (uint256 _fee) { _fee = (universalFee * (block.timestamp - _lastRebalance) * _totalDebt) / (MAX_BPS * ONE_YEAR); uint256 _maxFee = (_profit * maxProfitAsFee) / MAX_BPS; if (_fee > _maxFee) { _fee = _maxFee; } } ////////////////////////////// Only Governor ////////////////////////////// /** * @notice Migrate existing strategy to new strategy. * @dev Migrating strategy aka old and new strategy should be of same type. * @param _old Address of strategy being migrated * @param _new Address of new strategy */ function migrateStrategy(address _old, address _new) external onlyGovernor { require( IStrategy(_new).pool() == address(this) && IStrategy(_old).pool() == address(this), Errors.INVALID_STRATEGY ); IPoolAccountant(poolAccountant).migrateStrategy(_old, _new); IStrategy(_old).migrate(_new); } /** * Only Governor:: Update maximum profit that can be used as universal fee * @param _newMaxProfitAsFee New max profit as fee */ function updateMaximumProfitAsFee(uint256 _newMaxProfitAsFee) external onlyGovernor { require(_newMaxProfitAsFee != maxProfitAsFee, Errors.SAME_AS_PREVIOUS); emit UpdatedMaximumProfitAsFee(maxProfitAsFee, _newMaxProfitAsFee); maxProfitAsFee = _newMaxProfitAsFee; } /** * Only Governor:: Update minimum deposit limit * @param _newLimit New minimum deposit limit */ function updateMinimumDepositLimit(uint256 _newLimit) external onlyGovernor { require(_newLimit > 0, Errors.INVALID_INPUT); require(_newLimit != minDepositLimit, Errors.SAME_AS_PREVIOUS); emit UpdatedMinimumDepositLimit(minDepositLimit, _newLimit); minDepositLimit = _newLimit; } /** * @notice Update universal fee for this pool * @dev Format: 1500 = 15% fee, 100 = 1% * @param _newUniversalFee new universal fee */ function updateUniversalFee(uint256 _newUniversalFee) external onlyGovernor { require(_newUniversalFee <= MAX_BPS, Errors.FEE_LIMIT_REACHED); emit UpdatedUniversalFee(universalFee, _newUniversalFee); universalFee = _newUniversalFee; } /** * @notice Update pool rewards address for this pool * @param _newPoolRewards new pool rewards address */ function updatePoolRewards(address _newPoolRewards) external onlyGovernor { require(_newPoolRewards != address(0), Errors.INPUT_ADDRESS_IS_ZERO); emit UpdatedPoolRewards(poolRewards, _newPoolRewards); poolRewards = _newPoolRewards; } ///////////////////////////// Only Keeper /////////////////////////////// function pause() external onlyKeeper { _pause(); } function unpause() external onlyKeeper { _unpause(); } function shutdown() external onlyKeeper { _shutdown(); } function open() external onlyKeeper { _open(); } /// @notice Return list of keepers function keepers() external view returns (address[] memory) { return _keepers.values(); } function isKeeper(address _address) external view returns (bool) { return _keepers.contains(_address); } /** * @notice Add given address in keepers list. * @param _keeperAddress keeper address to add. */ function addKeeper(address _keeperAddress) external onlyKeeper { require(_keepers.add(_keeperAddress), Errors.ADD_IN_LIST_FAILED); } /** * @notice Remove given address from keepers list. * @param _keeperAddress keeper address to remove. */ function removeKeeper(address _keeperAddress) external onlyKeeper { require(_keepers.remove(_keeperAddress), Errors.REMOVE_FROM_LIST_FAILED); } /// @notice Return list of maintainers function maintainers() external view returns (address[] memory) { return _maintainers.values(); } function isMaintainer(address _address) external view returns (bool) { return _maintainers.contains(_address); } /** * @notice Add given address in maintainers list. * @param _maintainerAddress maintainer address to add. */ function addMaintainer(address _maintainerAddress) external onlyKeeper { require(_maintainers.add(_maintainerAddress), Errors.ADD_IN_LIST_FAILED); } /** * @notice Remove given address from maintainers list. * @param _maintainerAddress maintainer address to remove. */ function removeMaintainer(address _maintainerAddress) external onlyKeeper { require(_maintainers.remove(_maintainerAddress), Errors.REMOVE_FROM_LIST_FAILED); } /////////////////////////////////////////////////////////////////////////// }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IStrategy { function rebalance() external returns ( uint256 _profit, uint256 _loss, uint256 _payback ); function sweepERC20(address _fromToken) external; function withdraw(uint256 _amount) external; function feeCollector() external view returns (address); function isReservedToken(address _token) external view returns (bool); function keepers() external view returns (address[] memory); function migrate(address _newStrategy) external; function token() external view returns (address); function pool() external view returns (address); // solhint-disable-next-line func-name-mixedcase function VERSION() external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /// @title Errors library library Errors { string public constant INVALID_COLLATERAL_AMOUNT = "1"; // Collateral must be greater than 0 or > defined limit string public constant INVALID_SHARE_AMOUNT = "2"; // Share must be greater than 0 string public constant INVALID_INPUT_LENGTH = "3"; // Input array length must be greater than 0 string public constant INPUT_LENGTH_MISMATCH = "4"; // Input array length mismatch with another array length string public constant NOT_WHITELISTED_ADDRESS = "5"; // Caller is not whitelisted to withdraw without fee string public constant MULTI_TRANSFER_FAILED = "6"; // Multi transfer of tokens has failed string public constant FEE_COLLECTOR_NOT_SET = "7"; // Fee Collector is not set string public constant NOT_ALLOWED_TO_SWEEP = "8"; // Token is not allowed to sweep string public constant INSUFFICIENT_BALANCE = "9"; // Insufficient balance to performs operations to follow string public constant INPUT_ADDRESS_IS_ZERO = "10"; // Input address is zero string public constant FEE_LIMIT_REACHED = "11"; // Fee must be less than MAX_BPS string public constant ALREADY_INITIALIZED = "12"; // Data structure, contract, or logic already initialized and can not be called again string public constant ADD_IN_LIST_FAILED = "13"; // Cannot add address in address list string public constant REMOVE_FROM_LIST_FAILED = "14"; // Cannot remove address from address list string public constant STRATEGY_IS_ACTIVE = "15"; // Strategy is already active, an inactive strategy is required string public constant STRATEGY_IS_NOT_ACTIVE = "16"; // Strategy is not active, an active strategy is required string public constant INVALID_STRATEGY = "17"; // Given strategy is not a strategy of this pool string public constant DEBT_RATIO_LIMIT_REACHED = "18"; // Debt ratio limit reached. It must be less than MAX_BPS string public constant TOTAL_DEBT_IS_NOT_ZERO = "19"; // Strategy total debt must be 0 string public constant LOSS_TOO_HIGH = "20"; // Strategy reported loss must be less than current debt string public constant INVALID_MAX_BORROW_LIMIT = "21"; // Max borrow limit is beyond range. string public constant MAX_LIMIT_LESS_THAN_MIN = "22"; // Max limit should be greater than min limit. string public constant INVALID_SLIPPAGE = "23"; // Slippage should be less than MAX_BPS string public constant WRONG_RECEIPT_TOKEN = "24"; // Wrong receipt token address string public constant AAVE_FLASH_LOAN_NOT_ACTIVE = "25"; // aave flash loan is not active string public constant DYDX_FLASH_LOAN_NOT_ACTIVE = "26"; // DYDX flash loan is not active string public constant INVALID_FLASH_LOAN = "27"; // invalid-flash-loan string public constant INVALID_INITIATOR = "28"; // "invalid-initiator" string public constant INCORRECT_WITHDRAW_AMOUNT = "29"; // withdrawn amount is not correct string public constant NO_MARKET_ID_FOUND = "30"; // dydx flash loan no marketId found for token string public constant SAME_AS_PREVIOUS = "31"; // Input should not be same as previous value. string public constant INVALID_INPUT = "32"; // Generic invalid input error code }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./dependencies/openzeppelin/contracts/proxy/utils/Initializable.sol"; import "./dependencies/openzeppelin/contracts/utils/Context.sol"; import "./interfaces/vesper/IGovernable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (governor) that can be granted exclusive access to * specific functions. * * By default, the governor account will be the one that deploys the contract. This * can later be changed with {transferGovernorship}. * */ abstract contract Governable is IGovernable, Context, Initializable { address public governor; address private proposedGovernor; event UpdatedGovernor(address indexed previousGovernor, address indexed proposedGovernor); /** * @dev Initializes the contract setting the deployer as the initial governor. */ constructor() { address msgSender = _msgSender(); governor = msgSender; emit UpdatedGovernor(address(0), msgSender); } /** * @dev If inheriting child is using proxy then child contract can use * __Governable_init() function to initialization this contract */ // solhint-disable-next-line func-name-mixedcase function __Governable_init() internal initializer { address msgSender = _msgSender(); governor = msgSender; emit UpdatedGovernor(address(0), msgSender); } /** * @dev Throws if called by any account other than the governor. */ modifier onlyGovernor() { require(governor == _msgSender(), "not-governor"); _; } /** * @dev Transfers governorship of the contract to a new account (`proposedGovernor`). * Can only be called by the current owner. */ function transferGovernorship(address _proposedGovernor) external onlyGovernor { require(_proposedGovernor != address(0), "proposed-governor-is-zero"); proposedGovernor = _proposedGovernor; } /** * @dev Allows new governor to accept governorship of the contract. */ function acceptGovernorship() external { require(proposedGovernor == _msgSender(), "not-the-proposed-governor"); emit UpdatedGovernor(governor, proposedGovernor); governor = proposedGovernor; proposedGovernor = address(0); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./dependencies/openzeppelin/contracts/utils/Context.sol"; import "./interfaces/vesper/IPausable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * */ abstract contract Pausable is IPausable, Context { event Paused(address account); event Shutdown(address account); event Unpaused(address account); event Open(address account); bool public paused; bool public stopEverything; modifier whenNotPaused() { require(!paused, "paused"); _; } modifier whenPaused() { require(paused, "not-paused"); _; } modifier whenNotShutdown() { require(!stopEverything, "shutdown"); _; } modifier whenShutdown() { require(stopEverything, "not-shutdown"); _; } /// @dev Pause contract operations, if contract is not paused. function _pause() internal virtual whenNotPaused { paused = true; emit Paused(_msgSender()); } /// @dev Unpause contract operations, allow only if contract is paused and not shutdown. function _unpause() internal virtual whenPaused whenNotShutdown { paused = false; emit Unpaused(_msgSender()); } /// @dev Shutdown contract operations, if not already shutdown. function _shutdown() internal virtual whenNotShutdown { stopEverything = true; paused = true; emit Shutdown(_msgSender()); } /// @dev Open contract operations, if contract is in shutdown state function _open() internal virtual whenShutdown { stopEverything = false; emit Open(_msgSender()); } }
// SPDX-License-Identifier: MIT // solhint-disable-next-line compiler-version pragma solidity ^0.8.0; /** * @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 a proxied contract can't have 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. */ 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() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT 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' // solhint-disable-next-line max-line-length 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 // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } } else if (signature.length == 64) { // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { let vs := mload(add(signature, 0x40)) r := mload(add(signature, 0x20)) s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } } else { revert("ECDSA: invalid signature length"); } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value"); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /** * @notice Governable interface */ interface IGovernable { function governor() external view returns (address _governor); function transferGovernorship(address _proposedGovernor) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; /** * @notice Pausable interface */ interface IPausable { function paused() external view returns (bool); function stopEverything() external view returns (bool); function pause() external; function unpause() external; function shutdown() external; function open() external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IPoolAccountant { function decreaseDebt(address _strategy, uint256 _decreaseBy) external; function migrateStrategy(address _old, address _new) external; function reportEarning( address _strategy, uint256 _profit, uint256 _loss, uint256 _payback ) external returns (uint256 _actualPayback, uint256 _creditLine); function reportLoss(address _strategy, uint256 _loss) external; function availableCreditLimit(address _strategy) external view returns (uint256); function excessDebt(address _strategy) external view returns (uint256); function getStrategies() external view returns (address[] memory); function getWithdrawQueue() external view returns (address[] memory); function strategy(address _strategy) external view returns ( bool _active, uint256 _interestFee, // Obsolete uint256 _debtRate, // Obsolete uint256 _lastRebalance, uint256 _totalDebt, uint256 _totalLoss, uint256 _totalProfit, uint256 _debtRatio, uint256 _externalDepositFee ); function externalDepositFee() external view returns (uint256); function totalDebt() external view returns (uint256); function totalDebtOf(address _strategy) external view returns (uint256); function totalDebtRatio() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IPoolRewards { /// Emitted after reward added event RewardAdded(address indexed rewardToken, uint256 reward, uint256 rewardDuration); /// Emitted whenever any user claim rewards event RewardPaid(address indexed user, address indexed rewardToken, uint256 reward); /// Emitted after adding new rewards token into rewardTokens array event RewardTokenAdded(address indexed rewardToken, address[] existingRewardTokens); function claimReward(address) external; function notifyRewardAmount( address _rewardToken, uint256 _rewardAmount, uint256 _rewardDuration ) external; function notifyRewardAmount( address[] memory _rewardTokens, uint256[] memory _rewardAmounts, uint256[] memory _rewardDurations ) external; function updateReward(address) external; function claimable(address _account) external view returns (address[] memory _rewardTokens, uint256[] memory _claimableAmounts); function lastTimeRewardApplicable(address _rewardToken) external view returns (uint256); function rewardForDuration() external view returns (address[] memory _rewardTokens, uint256[] memory _rewardForDuration); function rewardPerToken() external view returns (address[] memory _rewardTokens, uint256[] memory _rewardPerTokenRate); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../../dependencies/openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "./IGovernable.sol"; import "./IPausable.sol"; interface IVesperPool is IGovernable, IPausable, IERC20Metadata { function calculateUniversalFee(uint256 _profit) external view returns (uint256 _fee); function deposit(uint256 _share) external; function multiTransfer(address[] memory _recipients, uint256[] memory _amounts) external returns (bool); function excessDebt(address _strategy) external view returns (uint256); function poolAccountant() external view returns (address); function poolRewards() external view returns (address); function reportEarning( uint256 _profit, uint256 _loss, uint256 _payback ) external; function reportLoss(uint256 _loss) external; function sweepERC20(address _fromToken) external; function withdraw(uint256 _amount) external; function keepers() external view returns (address[] memory); function isKeeper(address _address) external view returns (bool); function maintainers() external view returns (address[] memory); function isMaintainer(address _address) external view returns (bool); function pricePerShare() external view returns (uint256); function strategy(address _strategy) external view returns ( bool _active, uint256 _interestFee, // Obsolete uint256 _debtRate, // Obsolete uint256 _lastRebalance, uint256 _totalDebt, uint256 _totalLoss, uint256 _totalProfit, uint256 _debtRatio, uint256 _externalDepositFee ); function token() external view returns (IERC20); function tokensHere() external view returns (uint256); function totalDebtOf(address _strategy) external view returns (uint256); function totalValue() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../dependencies/openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "../dependencies/openzeppelin/contracts/utils/Context.sol"; // solhint-disable reason-string, no-empty-blocks ///@title Pool ERC20 to use with proxy. Inspired by OpenZeppelin ERC20 abstract contract PoolERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Sets the values for {name} and {symbol} for proxy */ // solhint-disable-next-line func-name-mixedcase function __ERC20_init(string memory name_, string memory symbol_) internal { _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 decimals of the token. default to 18 */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev Returns total supply of the token. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, 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}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), 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}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); uint256 currentAllowance = _allowances[sender][_msgSender()]; require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); _approve(sender, _msgSender(), currentAllowance - amount); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is 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: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); uint256 senderBalance = _balances[sender]; require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); _balances[sender] = senderBalance - amount; _balances[recipient] += amount; emit Transfer(sender, recipient, 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: * * - `to` 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); } /** * @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"); _balances[account] = accountBalance - amount; _totalSupply -= amount; emit Transfer(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 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 to 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 {} }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol"; import "../dependencies/openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./PoolERC20.sol"; ///@title Pool ERC20 Permit to use with proxy. Inspired by OpenZeppelin ERC20Permit // solhint-disable var-name-mixedcase abstract contract PoolERC20Permit is PoolERC20, IERC20Permit { bytes32 private constant _EIP712_VERSION = keccak256(bytes("1")); bytes32 private constant _EIP712_DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 private _CACHED_DOMAIN_SEPARATOR; bytes32 private _HASHED_NAME; uint256 private _CACHED_CHAIN_ID; /** * @dev See {IERC20Permit-nonces}. */ mapping(address => uint256) public override nonces; /** * @dev Initializes the domain separator using the `name` parameter, and setting `version` to `"1"`. * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ // solhint-disable-next-line func-name-mixedcase function __ERC20Permit_init(string memory name_) internal { _HASHED_NAME = keccak256(bytes(name_)); _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(_EIP712_DOMAIN_TYPEHASH, _HASHED_NAME, _EIP712_VERSION); } /** * @dev See {IERC20Permit-permit}. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual override { // solhint-disable-next-line not-rely-on-time require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); uint256 _currentNonce = nonces[owner]; bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _currentNonce, deadline)); bytes32 hash = keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash)); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); nonces[owner] = _currentNonce + 1; _approve(owner, spender, value); } /** * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() private view returns (bytes32) { if (block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_EIP712_DOMAIN_TYPEHASH, _HASHED_NAME, _EIP712_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 name, bytes32 version ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, name, version, block.chainid, address(this))); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "../dependencies/openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../dependencies/openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "../interfaces/vesper/IVesperPool.sol"; abstract contract PoolStorageV1 is IVesperPool { ///@notice Collateral token address IERC20 public token; /// @notice PoolAccountant address address public poolAccountant; /// @notice PoolRewards contract address address public poolRewards; address private feeWhitelistObsolete; // Obsolete in favor of AddressSet of feeWhitelist address private keepersObsolete; // Obsolete in favor of AddressSet of keepers address private maintainersObsolete; // Obsolete in favor of AddressSet of maintainers address private feeCollectorObsolete; // Fee collector address. Obsolete as there is no fee to collect uint256 private withdrawFeeObsolete; // Withdraw fee for this pool. Obsolete in favor of universal fee uint256 private decimalConversionFactorObsolete; // It can be used in converting value to/from 18 decimals bool internal withdrawInETH; // This flag will be used by VETH pool as switch to withdraw ETH or WETH } abstract contract PoolStorageV2 is PoolStorageV1 { EnumerableSet.AddressSet private _feeWhitelistObsolete; // Obsolete in favor of universal fee EnumerableSet.AddressSet internal _keepers; // List of keeper addresses EnumerableSet.AddressSet internal _maintainers; // List of maintainer addresses } abstract contract PoolStorageV3 is PoolStorageV2 { /// @notice Universal fee of this pool. Default to 2% uint256 public universalFee = 200; /// @notice Maximum percentage of profit that can be counted as universal fee. Default to 50% uint256 public maxProfitAsFee = 5_000; /// @notice Minimum deposit limit. /// @dev Do not set it to 0 as deposit() is checking if amount >= limit uint256 public minDepositLimit = 1; }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 100 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Open","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Shutdown","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":"uint256","name":"strategyDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"profit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"UniversalFeePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"proposedGovernor","type":"address"}],"name":"UpdatedGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMaxProfitAsFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxProfitAsFee","type":"uint256"}],"name":"UpdatedMaximumProfitAsFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldDepositLimit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDepositLimit","type":"uint256"}],"name":"UpdatedMinimumDepositLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousPoolRewards","type":"address"},{"indexed":true,"internalType":"address","name":"newPoolRewards","type":"address"}],"name":"UpdatedPoolRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldUniversalFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newUniversalFee","type":"uint256"}],"name":"UpdatedUniversalFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"previousWithdrawFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newWithdrawFee","type":"uint256"}],"name":"UpdatedWithdrawFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ONE_YEAR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeperAddress","type":"address"}],"name":"addKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_maintainerAddress","type":"address"}],"name":"addMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"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":"_strategy","type":"address"}],"name":"availableCreditLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"calculateMintage","outputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_profit","type":"uint256"}],"name":"calculateUniversalFee","outputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositAndClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"depositWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"excessDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategies","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawQueue","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_poolAccountant","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isKeeper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isMaintainer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keepers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maintainers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxProfitAsFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_old","type":"address"},{"internalType":"address","name":"_new","type":"address"}],"name":"migrateStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minDepositLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_recipients","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"multiTransfer","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":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"open","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolAccountant","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolRewards","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_keeperAddress","type":"address"}],"name":"removeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_maintainerAddress","type":"address"}],"name":"removeMaintainer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_profit","type":"uint256"},{"internalType":"uint256","name":"_loss","type":"uint256"},{"internalType":"uint256","name":"_payback","type":"uint256"}],"name":"reportEarning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_loss","type":"uint256"}],"name":"reportLoss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopEverything","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"strategy","outputs":[{"internalType":"bool","name":"_active","type":"bool"},{"internalType":"uint256","name":"_interestFee","type":"uint256"},{"internalType":"uint256","name":"_debtRate","type":"uint256"},{"internalType":"uint256","name":"_lastRebalance","type":"uint256"},{"internalType":"uint256","name":"_totalDebt","type":"uint256"},{"internalType":"uint256","name":"_totalLoss","type":"uint256"},{"internalType":"uint256","name":"_totalProfit","type":"uint256"},{"internalType":"uint256","name":"_debtRatio","type":"uint256"},{"internalType":"uint256","name":"_externalDepositFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_fromToken","type":"address"}],"name":"sweepERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensHere","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategy","type":"address"}],"name":"totalDebtOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebtRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_proposedGovernor","type":"address"}],"name":"transferGovernorship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"universalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxProfitAsFee","type":"uint256"}],"name":"updateMaximumProfitAsFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newLimit","type":"uint256"}],"name":"updateMinimumDepositLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPoolRewards","type":"address"}],"name":"updatePoolRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newUniversalFee","type":"uint256"}],"name":"updateUniversalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"whitelistedWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"withdrawAndClaim","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405260c8601d55611388601e556001601f553480156200002157600080fd5b50604051620048f5380380620048f583398101604081905262000044916200027b565b8251839083906200005d90600390602085019062000108565b5080516200007390600490602084019062000108565b5050506000620000886200010460201b60201c565b600a80546001600160a01b0319166001600160a01b038316908117909155604051919250906000907fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d0908290a3506001600c55600d80546001600160a01b0319166001600160a01b039290921691909117905550620003459050565b3390565b828054620001169062000308565b90600052602060002090601f0160209004810192826200013a576000855562000185565b82601f106200015557805160ff191683800117855562000185565b8280016001018555821562000185579182015b828111156200018557825182559160200191906001019062000168565b506200019392915062000197565b5090565b5b8082111562000193576000815560010162000198565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001d657600080fd5b81516001600160401b0380821115620001f357620001f3620001ae565b604051601f8301601f19908116603f011681019082821181831017156200021e576200021e620001ae565b816040528381526020925086838588010111156200023b57600080fd5b600091505b838210156200025f578582018301518183018401529082019062000240565b83821115620002715760008385830101525b9695505050505050565b6000806000606084860312156200029157600080fd5b83516001600160401b0380821115620002a957600080fd5b620002b787838801620001c4565b94506020860151915080821115620002ce57600080fd5b50620002dd86828701620001c4565b604086015190935090506001600160a01b0381168114620002fd57600080fd5b809150509250925092565b600181811c908216806200031d57607f821691505b602082108114156200033f57634e487b7160e01b600052602260045260246000fd5b50919050565b6145a080620003556000396000f3fe608060405234801561001057600080fd5b50600436106103715760003560e01c80638d3d0a26116101d5578063c12d636b11610105578063e00af4a7116100a8578063e00af4a7146107e1578063f3b27bc3146107f4578063fc0c546a146107fc578063fc0e74d11461080f578063fc7b9c1814610817578063fcfff16f1461081f578063fd967f4714610827578063ff643a7c14610830578063ffa1ad741461084357600080fd5b8063c12d636b1461072e578063d4c3eea014610741578063d505accf14610749578063d53ddc261461075c578063d8baf7cf1461076f578063dd57366a14610782578063dd62ed3e14610795578063ddd6d260146107ce57600080fd5b80639fd5be18116101785780639fd5be18146106a3578063a9059cbb146106ac578063a941a90e146106bf578063b49a60bb146106d2578063b64321ec146106da578063b6aa515b146106ed578063b6b55f2514610700578063b8cb343d14610713578063c01e0d401461071b57600080fd5b80638d3d0a261461062c5780638f15b4141461063f578063940c408214610652578063951dc22c1461066557806395d89b411461066d57806399530b06146106755780639b6da8df1461067d5780639f2b28331461069057600080fd5b80633644e515116102b05780635c975abb116102535780635c975abb146105725780635f895e54146105865780636b453c1f1461058f5780636ba42aaa146105a25780636cb56d19146105b557806370a08231146105c85780637ecebe00146105f15780638456cb59146106115780638bc6beb21461061957600080fd5b80633644e515146105045780633e7729251461050c5780633f4ba83a146105155780634032b72b1461051d578063448a1047146105305780634938649a1461054357806349eeb860146105575780634a970be71461055f57600080fd5b806318160ddd1161031857806318160ddd146104405780631e89d54514610448578063228bfd9f1461045b57806323b872dd146104b45780632df9eab9146104c75780632e1a7d4d146104cf578063313ce567146104e257806332dd0f49146104f157600080fd5b806305bed0461461037657806306fdde031461038b578063095ea7b3146103a95780630c340a24146103cc5780630da3fe20146103ec57806311183052146103ff57806314ae9f2e1461041457806316d3bfbb14610427575b600080fd5b610389610384366004613ba0565b610867565b005b610393610ae8565b6040516103a09190613bf8565b60405180910390f35b6103bc6103b7366004613c40565b610b7a565b60405190151581526020016103a0565b600a546103df906001600160a01b031681565b6040516103a09190613c6c565b6103896103fa366004613c80565b610b91565b610407610c7d565b6040516103a09190613c99565b610389610422366004613ce6565b610d03565b6104326301e1338081565b6040519081526020016103a0565b600254610432565b6103bc610456366004613d4f565b610d88565b61046e610469366004613ce6565b610e6e565b604080519915158a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e0830152610100820152610120016103a0565b6103bc6104c2366004613dbb565b610f1f565b610432610fd2565b6103896104dd366004613c80565b61104f565b604051601281526020016103a0565b6104326104ff366004613c80565b6110c0565b6104326110cc565b610432601e5481565b6103896110d6565b61038961052b366004613ce6565b611119565b61038961053e366004613c80565b611196565b600b546103bc90600160a81b900460ff1681565b6104076111f1565b61038961056d366004613e0b565b6111fd565b600b546103bc90600160a01b900460ff1681565b610432601d5481565b61038961059d366004613ce6565b611304565b6103bc6105b0366004613ce6565b611348565b6103896105c3366004613e54565b611355565b6104326105d6366004613ce6565b6001600160a01b031660009081526020819052604090205490565b6104326105ff366004613ce6565b60096020526000908152604090205481565b610389611594565b600f546103df906001600160a01b031681565b61038961063a366004613c80565b6115d5565b61038961064d366004613f44565b61167d565b610389610660366004613ce6565b61185b565b610407611922565b61039361192e565b61043261193d565b61038961068b366004613c80565b611a16565b61043261069e366004613ce6565b611ac1565b610432601f5481565b6103bc6106ba366004613c40565b611b42565b6103896106cd366004613c80565b611b4f565b610407611baa565b6104326106e8366004613ce6565b611bef565b6103896106fb366004613ce6565b611c20565b61038961070e366004613c80565b611cbe565b610432611d22565b610432610729366004613c80565b611d6b565b600e546103df906001600160a01b031681565b610432611e5f565b610389610757366004613fcd565b611ef9565b61043261076a366004613ce6565b6120b9565b61038961077d366004613ce6565b6120ea565b6103bc610790366004613ce6565b61212e565b6104326107a3366004613e54565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6103896107dc366004613c80565b61213b565b6103896107ef366004613ce6565b6121a2565b6103896122bd565b600d546103df906001600160a01b031681565b610389612379565b6104326123ba565b6103896123ff565b61043261271081565b61038961083e366004613c80565b612440565b610393604051806040016040528060058152602001641a9718171960d91b81525081565b3383156109dc57600e5460405163228bfd9f60e01b815260009182916001600160a01b039091169063228bfd9f906108a3908690600401613c6c565b6101206040518083038186803b1580156108bc57600080fd5b505afa1580156108d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f49190614053565b5050505094509450505050600061090c83838961249b565b905080156109d857610996846001600160a01b031663c415b95c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561095057600080fd5b505afa158015610964573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098891906140c3565b6109918361250e565b612573565b60408051838152602081018990529081018290527f692ef79cc704efab4328e6c217b5fb3b1045d0a0314e3e8137029bcb2d59ce4a9060600160405180910390a15b5050505b600e5460405163a066654b60e01b81526001600160a01b038381166004830152602482018790526044820186905260648201859052600092839291169063a066654b906084016040805180830381600087803b158015610a3b57600080fd5b505af1158015610a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7391906140e0565b90925090506000610a84838861411a565b905081811015610ab457610aaf84610a9c8385614132565b600d546001600160a01b03169190612640565b610adf565b81811115610adf57610adf8430610acb8585614132565b600d546001600160a01b031692919061269b565b50505050505050565b606060038054610af790614149565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2390614149565b8015610b705780601f10610b4557610100808354040283529160200191610b70565b820191906000526020600020905b815481529060010190602001808311610b5357829003601f168201915b5050505050905090565b6000610b873384846126d9565b5060015b92915050565b600a546001600160a01b03163314610bc45760405162461bcd60e51b8152600401610bbb90614184565b60405180910390fd5b604080518082019091526002815261199960f11b602082015281610bfb5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601f5481141560405180604001604052806002815260200161333160f01b81525090610c3b5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601f5460408051918252602082018390527f25c9f41f0fb7a055d44b070262516fbd0111daea3b55d40fae1983827dc99292910160405180910390a1601f55565b600e546040805163088c182960e11b815290516060926001600160a01b0316916311183052916004808301926000929190829003018186803b158015610cc257600080fd5b505afa158015610cd6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cfe91908101906141aa565b905090565b600a546001600160a01b0316331480610d245750610d24335b6019906127fe565b610d405760405162461bcd60e51b8152600401610bbb9061425c565b610d4b601982612820565b604051806040016040528060028152602001610c4d60f21b81525090610d845760405162461bcd60e51b8152600401610bbb9190613bf8565b5050565b6040805180820190915260018152600d60fa1b6020820152600090848314610dc35760405162461bcd60e51b8152600401610bbb9190613bf8565b5060005b84811015610e6257610e17868683818110610de457610de4614282565b9050602002016020810190610df99190613ce6565b858584818110610e0b57610e0b614282565b90506020020135611b42565b604051806040016040528060018152602001601b60f91b81525090610e4f5760405162461bcd60e51b8152600401610bbb9190613bf8565b5080610e5a81614298565b915050610dc7565b50600195945050505050565b600e5460405163228bfd9f60e01b8152600091829182918291829182918291829182916001600160a01b03169063228bfd9f90610eaf908d90600401613c6c565b6101206040518083038186803b158015610ec857600080fd5b505afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f009190614053565b9850985098509850985098509850985098509193959799909294969850565b6000610f2c848484612835565b6001600160a01b038416600090815260016020908152604080832033845290915290205482811015610fb15760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b6064820152608401610bbb565b610fc58533610fc08685614132565b6126d9565b60019150505b9392505050565b600e5460408051632df9eab960e01b815290516000926001600160a01b031691632df9eab9916004808301926020929190829003018186803b15801561101757600080fd5b505afa15801561102b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfe91906142b3565b6002600c5414156110725760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a81b900460ff16156110a15760405162461bcd60e51b8152600401610bbb90614303565b6110af33612916565b612916565b6110b881612957565b506001600c55565b6000610b8b3383612a13565b6000610cfe612ab8565b600a546001600160a01b03163314806110f357506110f333610d1c565b61110f5760405162461bcd60e51b8152600401610bbb9061425c565b611117612b33565b565b600a546001600160a01b0316331480611136575061113633610d1c565b6111525760405162461bcd60e51b8152600401610bbb9061425c565b61115d601982612bea565b60405180604001604052806002815260200161313360f01b81525090610d845760405162461bcd60e51b8152600401610bbb9190613bf8565b6002600c5414156111b95760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a81b900460ff16156111e85760405162461bcd60e51b8152600401610bbb90614303565b6110b881612bff565b6060610cfe601b612c11565b6002600c5414156112205760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a01b900460ff161561124f5760405162461bcd60e51b8152600401610bbb90614325565b600d546001600160a01b031663d505accf336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c4810184905260e401600060405180830381600087803b1580156112cd57600080fd5b505af11580156112e1573d6000803e3d6000fd5b505050506112ef6110aa3390565b6112f885612c1e565b50506001600c55505050565b600a546001600160a01b0316331480611321575061132133610d1c565b61133d5760405162461bcd60e51b8152600401610bbb9061425c565b61115d601b82612bea565b6000610b8b6019836127fe565b600a546001600160a01b0316331461137f5760405162461bcd60e51b8152600401610bbb90614184565b306001600160a01b0316816001600160a01b03166316f0115b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c257600080fd5b505afa1580156113d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fa91906140c3565b6001600160a01b03161480156114915750306001600160a01b0316826001600160a01b03166316f0115b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561144e57600080fd5b505afa158015611462573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148691906140c3565b6001600160a01b0316145b60405180604001604052806002815260200161313760f01b815250906114ca5760405162461bcd60e51b8152600401610bbb9190613bf8565b50600e54604051636cb56d1960e01b81526001600160a01b038481166004830152838116602483015290911690636cb56d1990604401600060405180830381600087803b15801561151a57600080fd5b505af115801561152e573d6000803e3d6000fd5b505060405163ce5494bb60e01b81526001600160a01b038516925063ce5494bb915061155e908490600401613c6c565b600060405180830381600087803b15801561157857600080fd5b505af115801561158c573d6000803e3d6000fd5b505050505050565b600a546001600160a01b03163314806115b157506115b133610d1c565b6115cd5760405162461bcd60e51b8152600401610bbb9061425c565b611117612c8c565b600a546001600160a01b031633146115ff5760405162461bcd60e51b8152600401610bbb90614184565b604080518082019091526002815261313160f01b602082015261271082111561163b5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601d5460408051918252602082018390527f905d672396c48f9d1e13c57aec0819f00d39364ab4bf40a46a687aa607b67d81910160405180910390a1601d55565b600554610100900460ff1680611696575060055460ff16155b6116b25760405162461bcd60e51b8152600401610bbb90614345565b600554610100900460ff161580156116d4576005805461ffff19166101011790555b604080518082019091526002815261031360f41b60208201526001600160a01b0384166117145760405162461bcd60e51b8152600401610bbb9190613bf8565b50604080518082019091526002815261031360f41b60208201526001600160a01b0383166117555760405162461bcd60e51b8152600401610bbb9190613bf8565b506117608585612cf1565b61176985612d18565b611771612d97565b600d80546001600160a01b0319166001600160a01b03851617905561179833601990612bea565b60405180604001604052806002815260200161313360f01b815250906117d15760405162461bcd60e51b8152600401610bbb9190613bf8565b506117dd601b33612bea565b60405180604001604052806002815260200161313360f01b815250906118165760405162461bcd60e51b8152600401610bbb9190613bf8565b50600e80546001600160a01b0319166001600160a01b03841617905560c8601d55611388601e556001601f558015611854576005805461ff00191690555b5050505050565b600a546001600160a01b031633146118855760405162461bcd60e51b8152600401610bbb90614184565b604080518082019091526002815261031360f41b60208201526001600160a01b0382166118c55760405162461bcd60e51b8152600401610bbb9190613bf8565b50600f546040516001600160a01b038084169216907fe239974dad08ac696e723caf1886bd0b5afc0870088f9a1266082757f824927690600090a3600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6060610cfe6019612c11565b606060048054610af790614149565b600061194860025490565b15806119595750611957611e5f565b155b156119ef57600d60009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156119ac57600080fd5b505afa1580156119c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e49190614393565b610cfe90600a614494565b6002546119fa611e5f565b611a0c90670de0b6b3a76400006144a3565b610cfe91906144c2565b600a546001600160a01b03163314611a405760405162461bcd60e51b8152600401610bbb90614184565b601e5481141560405180604001604052806002815260200161333160f01b81525090611a7f5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601e5460408051918252602082018390527fafe4d3ceb3295a8d4ef49288a92d32d94e39396e823d414b81caff61b9fc3990910160405180910390a1601e55565b600e54604051639f2b283360e01b81526000916001600160a01b031690639f2b283390611af2908590600401613c6c565b60206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8b91906142b3565b6000610b87338484612835565b6002600c541415611b725760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a01b900460ff1615611ba15760405162461bcd60e51b8152600401610bbb90614325565b6110b881612e45565b600e546040805163b49a60bb60e01b815290516060926001600160a01b03169163b49a60bb916004808301926000929190829003018186803b158015610cc257600080fd5b600e54604051632d90c87b60e21b81526000916001600160a01b03169063b64321ec90611af2908590600401613c6c565b600a546001600160a01b03163314611c4a5760405162461bcd60e51b8152600401610bbb90614184565b6001600160a01b038116611c9c5760405162461bcd60e51b815260206004820152601960248201527870726f706f7365642d676f7665726e6f722d69732d7a65726f60381b6044820152606401610bbb565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6002600c541415611ce15760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a01b900460ff1615611d105760405162461bcd60e51b8152600401610bbb90614325565b611d1933612916565b6110b881612c1e565b600d546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d53903090600401613c6c565b60206040518083038186803b15801561101757600080fd5b6000601f54821015604051806040016040528060018152602001603160f81b81525090611dab5760405162461bcd60e51b8152600401610bbb9190613bf8565b506000612710600e60009054906101000a90046001600160a01b03166001600160a01b031663346162d56040518163ffffffff1660e01b815260040160206040518083038186803b158015611dff57600080fd5b505afa158015611e13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3791906142b3565b611e4190856144a3565b611e4b91906144c2565b9050610fcb611e5a8285614132565b61250e565b6000611e69611d22565b600e60009054906101000a90046001600160a01b03166001600160a01b031663fc7b9c186040518163ffffffff1660e01b815260040160206040518083038186803b158015611eb757600080fd5b505afa158015611ecb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eef91906142b3565b610cfe919061411a565b83421115611f495760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610bbb565b6001600160a01b0387811660008181526009602090815260408083205481517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98185015280830195909552948b166060850152608084018a905260a0840185905260c08085018a90528151808603909101815260e09094019052825192019190912090611fd4612ab8565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050600061201a82888888612e57565b90508a6001600160a01b0316816001600160a01b03161461207d5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610bbb565b61208884600161411a565b6001600160a01b038c166000908152600960205260409020556120ac8b8b8b6126d9565b5050505050505050505050565b600e54604051636a9eee1360e11b81526000916001600160a01b03169063d53ddc2690611af2908590600401613c6c565b600a546001600160a01b0316331480612107575061210733610d1c565b6121235760405162461bcd60e51b8152600401610bbb9061425c565b610d4b601b82612820565b6000610b8b601b836127fe565b801561219f57600e546001600160a01b0316637f13086e33836040518363ffffffff1660e01b81526004016121719291906144e4565b600060405180830381600087803b15801561218b57600080fd5b505af1158015611854573d6000803e3d6000fd5b50565b600a546001600160a01b03163314806121bf57506121bf33610d1c565b6121db5760405162461bcd60e51b8152600401610bbb9061425c565b600d546040805180820190915260018152600760fb1b6020820152906001600160a01b03838116911614156122235760405162461bcd60e51b8152600401610bbb9190613bf8565b50600a546040516370a0823160e01b815261219f916001600160a01b0390811691908416906370a082319061225c903090600401613c6c565b60206040518083038186803b15801561227457600080fd5b505afa158015612288573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ac91906142b3565b6001600160a01b0384169190612640565b600b546001600160a01b031633146123135760405162461bcd60e51b81526020600482015260196024820152783737ba16ba343296b83937b837b9b2b216b3b7bb32b93737b960391b6044820152606401610bbb565b600b54600a546040516001600160a01b0392831692909116907fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d090600090a3600b8054600a80546001600160a01b03199081166001600160a01b03841617909155169055565b600a546001600160a01b0316331480612396575061239633610d1c565b6123b25760405162461bcd60e51b8152600401610bbb9061425c565b611117612fe8565b600e5460408051631f8f738360e31b815290516000926001600160a01b03169163fc7b9c18916004808301926020929190829003018186803b15801561101757600080fd5b600a546001600160a01b031633148061241c575061241c33610d1c565b6124385760405162461bcd60e51b8152600401610bbb9061425c565b61111761304e565b6002600c5414156124635760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a81b900460ff16156124925760405162461bcd60e51b8152600401610bbb90614303565b6110af336130ca565b60006124ad6301e133806127106144a3565b836124b88642614132565b601d546124c591906144a3565b6124cf91906144a3565b6124d991906144c2565b90506000612710601e54846124ee91906144a3565b6124f891906144c2565b905080821115612506578091505b509392505050565b60008061251961193d565b61252b84670de0b6b3a76400006144a3565b61253591906144c2565b9050670de0b6b3a764000061254861193d565b61255290836144a3565b61255c91906144c2565b83116125685780610fcb565b610fcb81600161411a565b6001600160a01b0382166125c95760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610bbb565b80600260008282546125db919061411a565b90915550506001600160a01b0382166000908152602081905260408120805483929061260890849061411a565b90915550506040518181526001600160a01b0383169060009060008051602061454b8339815191529060200160405180910390a35050565b6126968363a9059cbb60e01b848460405160240161265f9291906144e4565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261310b565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526126d39085906323b872dd60e01b9060840161265f565b50505050565b6001600160a01b03831661273b5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610bbb565b6001600160a01b03821661279c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610bbb565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03811660009081526001830160205260408120541515610fcb565b6000610fcb836001600160a01b0384166131dd565b600f546001600160a01b03161561290b57600f5460405163632447c960e01b81526001600160a01b039091169063632447c990612876908690600401613c6c565b600060405180830381600087803b15801561289057600080fd5b505af11580156128a4573d6000803e3d6000fd5b5050600f5460405163632447c960e01b81526001600160a01b03909116925063632447c991506128d8908590600401613c6c565b600060405180830381600087803b1580156128f257600080fd5b505af1158015612906573d6000803e3d6000fd5b505050505b6126968383836132d0565b600f546001600160a01b03161561219f57600f5460405163632447c960e01b81526001600160a01b039091169063632447c990612171908490600401613c6c565b6040805180820190915260018152601960f91b60208201528161298d5760405162461bcd60e51b8152600401610bbb9190613bf8565b5060008061299a83613496565b9150915080156129bf5760006129af8361250e565b9050838110156129bd578093505b505b6129c93384613543565b6129d282613680565b50604080518481526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a2505050565b600e5460405163228bfd9f60e01b8152600091829182916001600160a01b03169063228bfd9f90612a48908890600401613c6c565b6101206040518083038186803b158015612a6157600080fd5b505afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190614053565b5050505094509450505050612aaf82828661249b565b95945050505050565b6000600854461415612acb575060065490565b6007546040805180820190915260018152603160f81b602090910152610cfe907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f907fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc661369d565b600b54600160a01b900460ff16612b795760405162461bcd60e51b815260206004820152600a6024820152691b9bdd0b5c185d5cd95960b21b6044820152606401610bbb565b600b54600160a81b900460ff1615612ba35760405162461bcd60e51b8152600401610bbb90614303565b600b805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051612be09190613c6c565b60405180910390a1565b6000610fcb836001600160a01b0384166136e6565b612c08336130ca565b61219f81612957565b60606000610fcb83613735565b6000612c2982611d6b565b9050612c4333600d546001600160a01b031690308561269b565b612c4d3382612573565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a25050565b600b54600160a01b900460ff1615612cb65760405162461bcd60e51b8152600401610bbb90614325565b600b805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612bd33390565b8151612d04906003906020850190613b10565b508051612696906004906020840190613b10565b80516020808301919091206007819055466008556040805180820190915260018152603160f81b920191909152612d91907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f907fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc661369d565b60065550565b600554610100900460ff1680612db0575060055460ff16155b612dcc5760405162461bcd60e51b8152600401610bbb90614345565b600554610100900460ff16158015612dee576005805461ffff19166101011790555b600a80546001600160a01b0319163390811790915560405181906000907fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d0908290a350801561219f576005805461ff001916905550565b612e4e336130ca565b61219f81612c1e565b60006fa2a8918ca85bafe22016d0b997e4df60600160ff1b03821115612eca5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610bbb565b8360ff16601b1480612edf57508360ff16601c145b612f365760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610bbb565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612f8a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612aaf5760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610bbb565b600b54600160a81b900460ff16156130125760405162461bcd60e51b8152600401610bbb90614303565b600b805461ffff60a01b191661010160a01b1790557f28b4c24cb1012c094cd2f59f98e89d791973295f8fda6eaa118022d6d318960a33612bd3565b600b54600160a81b900460ff166130965760405162461bcd60e51b815260206004820152600c60248201526b3737ba16b9b43aba3237bbb760a11b6044820152606401610bbb565b600b805460ff60a81b191690557fece7583a70a505ef0e36d4dec768f5ae597713e09c26011022599ee01abdabfc33612bd3565b600f546001600160a01b03161561219f57600f5460405163d279c19160e01b81526001600160a01b039091169063d279c19190612171908490600401613c6c565b6000613160826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137919092919063ffffffff16565b805190915015612696578080602001905181019061317e91906144fd565b6126965760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610bbb565b600081815260018301602052604081205480156132c6576000613201600183614132565b855490915060009061321590600190614132565b905081811461327a57600086600001828154811061323557613235614282565b906000526020600020015490508087600001848154811061325857613258614282565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061328b5761328b614518565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610b8b565b6000915050610b8b565b6001600160a01b0383166133345760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610bbb565b6001600160a01b0382166133965760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610bbb565b6001600160a01b0383166000908152602081905260409020548181101561340e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610bbb565b6134188282614132565b6001600160a01b03808616600090815260208190526040808220939093559085168152908120805484929061344e90849061411a565b92505081905550826001600160a01b0316846001600160a01b031660008051602061454b8339815191528460405161348891815260200190565b60405180910390a350505050565b6000806000670de0b6b3a76400006134ac61193d565b6134b690866144a3565b6134c091906144c2565b905060006134cc611d22565b905081935080821115613505576134eb6134e68284614132565b6137a8565b6134f3611d22565b90508082111561350557809350600192505b6040805180820190915260018152603160f81b60208201528461353b5760405162461bcd60e51b8152600401610bbb9190613bf8565b505050915091565b6001600160a01b0382166135a35760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610bbb565b6001600160a01b038216600090815260208190526040902054818110156136175760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610bbb565b6136218282614132565b6001600160a01b0384166000908152602081905260408120919091556002805484929061364f908490614132565b90915550506040518281526000906001600160a01b0385169060008051602061454b833981519152906020016127f1565b600061369933600d546001600160a01b03169084612640565b5090565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600081815260018301602052604081205461372d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610b8b565b506000610b8b565b60608160000180548060200260200160405190810160405280929190818152602001828054801561378557602002820191906000526020600020905b815481526020019060010190808311613771575b50505050509050919050565b60606137a084846000856139af565b949350505050565b6000806000806000806137b9610c7d565b805190915060005b818110156139a45760006137d5858b614132565b905060008483815181106137eb576137eb614282565b6020908102919091010151600e54604051639f2b283360e01b81529192506001600160a01b031690639f2b283390613827908490600401613c6c565b60206040518083038186803b15801561383f57600080fd5b505afa158015613853573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387791906142b3565b995089613885575050613992565b89821115613891578991505b613899611d22565b604051632e1a7d4d60e01b8152600481018490529098506001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b1580156138de57600080fd5b505af19250505080156138ef575060015b6138fa575050613992565b613902611d22565b985061390e888a614132565b600e54604051632fb9ba3160e01b81529198506001600160a01b031690632fb9ba31906139419084908b906004016144e4565b600060405180830381600087803b15801561395b57600080fd5b505af115801561396f573d6000803e3d6000fd5b50505050868661397f919061411a565b95508a861061398f5750506139a4565b50505b8061399c81614298565b9150506137c1565b505050505050505050565b606082471015613a105760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610bbb565b843b613a5e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bbb565b600080866001600160a01b03168587604051613a7a919061452e565b60006040518083038185875af1925050503d8060008114613ab7576040519150601f19603f3d011682016040523d82523d6000602084013e613abc565b606091505b5091509150613acc828286613ad7565b979650505050505050565b60608315613ae6575081610fcb565b825115613af65782518084602001fd5b8160405162461bcd60e51b8152600401610bbb9190613bf8565b828054613b1c90614149565b90600052602060002090601f016020900481019282613b3e5760008555613b84565b82601f10613b5757805160ff1916838001178555613b84565b82800160010185558215613b84579182015b82811115613b84578251825591602001919060010190613b69565b506136999291505b808211156136995760008155600101613b8c565b600080600060608486031215613bb557600080fd5b505081359360208301359350604090920135919050565b60005b83811015613be7578181015183820152602001613bcf565b838111156126d35750506000910152565b6020815260008251806020840152613c17816040850160208701613bcc565b601f01601f19169190910160400192915050565b6001600160a01b038116811461219f57600080fd5b60008060408385031215613c5357600080fd5b8235613c5e81613c2b565b946020939093013593505050565b6001600160a01b0391909116815260200190565b600060208284031215613c9257600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015613cda5783516001600160a01b031683529284019291840191600101613cb5565b50909695505050505050565b600060208284031215613cf857600080fd5b8135610fcb81613c2b565b60008083601f840112613d1557600080fd5b50813567ffffffffffffffff811115613d2d57600080fd5b6020830191508360208260051b8501011115613d4857600080fd5b9250929050565b60008060008060408587031215613d6557600080fd5b843567ffffffffffffffff80821115613d7d57600080fd5b613d8988838901613d03565b90965094506020870135915080821115613da257600080fd5b50613daf87828801613d03565b95989497509550505050565b600080600060608486031215613dd057600080fd5b8335613ddb81613c2b565b92506020840135613deb81613c2b565b929592945050506040919091013590565b60ff8116811461219f57600080fd5b600080600080600060a08688031215613e2357600080fd5b85359450602086013593506040860135613e3c81613dfc565b94979396509394606081013594506080013592915050565b60008060408385031215613e6757600080fd5b8235613e7281613c2b565b91506020830135613e8281613c2b565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613ecc57613ecc613e8d565b604052919050565b600082601f830112613ee557600080fd5b813567ffffffffffffffff811115613eff57613eff613e8d565b613f12601f8201601f1916602001613ea3565b818152846020838601011115613f2757600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215613f5a57600080fd5b843567ffffffffffffffff80821115613f7257600080fd5b613f7e88838901613ed4565b95506020870135915080821115613f9457600080fd5b50613fa187828801613ed4565b9350506040850135613fb281613c2b565b91506060850135613fc281613c2b565b939692955090935050565b600080600080600080600060e0888a031215613fe857600080fd5b8735613ff381613c2b565b9650602088013561400381613c2b565b95506040880135945060608801359350608088013561402181613dfc565b9699959850939692959460a0840135945060c09093013592915050565b8051801515811461404e57600080fd5b919050565b60008060008060008060008060006101208a8c03121561407257600080fd5b61407b8a61403e565b985060208a0151975060408a0151965060608a0151955060808a0151945060a08a0151935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b6000602082840312156140d557600080fd5b8151610fcb81613c2b565b600080604083850312156140f357600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b6000821982111561412d5761412d614104565b500190565b60008282101561414457614144614104565b500390565b600181811c9082168061415d57607f821691505b6020821081141561417e57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b3737ba16b3b7bb32b93737b960a11b604082015260600190565b600060208083850312156141bd57600080fd5b825167ffffffffffffffff808211156141d557600080fd5b818501915085601f8301126141e957600080fd5b8151818111156141fb576141fb613e8d565b8060051b915061420c848301613ea3565b818152918301840191848101908884111561422657600080fd5b938501935b83851015614250578451925061424083613c2b565b828252938501939085019061422b565b98975050505050505050565b6020808252600c908201526b3737ba16b096b5b2b2b832b960a11b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006000198214156142ac576142ac614104565b5060010190565b6000602082840312156142c557600080fd5b5051919050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526008908201526739b43aba3237bbb760c11b604082015260600190565b6020808252600690820152651c185d5cd95960d21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000602082840312156143a557600080fd5b8151610fcb81613dfc565b600181815b808511156143eb5781600019048211156143d1576143d1614104565b808516156143de57918102915b93841c93908002906143b5565b509250929050565b60008261440257506001610b8b565b8161440f57506000610b8b565b8160018114614425576002811461442f5761444b565b6001915050610b8b565b60ff84111561444057614440614104565b50506001821b610b8b565b5060208310610133831016604e8410600b841016171561446e575081810a610b8b565b61447883836143b0565b806000190482111561448c5761448c614104565b029392505050565b6000610fcb60ff8416836143f3565b60008160001904831182151516156144bd576144bd614104565b500290565b6000826144df57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03929092168252602082015260400190565b60006020828403121561450f57600080fd5b610fcb8261403e565b634e487b7160e01b600052603160045260246000fd5b60008251614540818460208701613bcc565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220e86c694a8614e406b22780f263b0ec173754481a0904cd83ca58cf5b7c14538064736f6c63430008090033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b56657370657220706f6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576506f6f6c000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103715760003560e01c80638d3d0a26116101d5578063c12d636b11610105578063e00af4a7116100a8578063e00af4a7146107e1578063f3b27bc3146107f4578063fc0c546a146107fc578063fc0e74d11461080f578063fc7b9c1814610817578063fcfff16f1461081f578063fd967f4714610827578063ff643a7c14610830578063ffa1ad741461084357600080fd5b8063c12d636b1461072e578063d4c3eea014610741578063d505accf14610749578063d53ddc261461075c578063d8baf7cf1461076f578063dd57366a14610782578063dd62ed3e14610795578063ddd6d260146107ce57600080fd5b80639fd5be18116101785780639fd5be18146106a3578063a9059cbb146106ac578063a941a90e146106bf578063b49a60bb146106d2578063b64321ec146106da578063b6aa515b146106ed578063b6b55f2514610700578063b8cb343d14610713578063c01e0d401461071b57600080fd5b80638d3d0a261461062c5780638f15b4141461063f578063940c408214610652578063951dc22c1461066557806395d89b411461066d57806399530b06146106755780639b6da8df1461067d5780639f2b28331461069057600080fd5b80633644e515116102b05780635c975abb116102535780635c975abb146105725780635f895e54146105865780636b453c1f1461058f5780636ba42aaa146105a25780636cb56d19146105b557806370a08231146105c85780637ecebe00146105f15780638456cb59146106115780638bc6beb21461061957600080fd5b80633644e515146105045780633e7729251461050c5780633f4ba83a146105155780634032b72b1461051d578063448a1047146105305780634938649a1461054357806349eeb860146105575780634a970be71461055f57600080fd5b806318160ddd1161031857806318160ddd146104405780631e89d54514610448578063228bfd9f1461045b57806323b872dd146104b45780632df9eab9146104c75780632e1a7d4d146104cf578063313ce567146104e257806332dd0f49146104f157600080fd5b806305bed0461461037657806306fdde031461038b578063095ea7b3146103a95780630c340a24146103cc5780630da3fe20146103ec57806311183052146103ff57806314ae9f2e1461041457806316d3bfbb14610427575b600080fd5b610389610384366004613ba0565b610867565b005b610393610ae8565b6040516103a09190613bf8565b60405180910390f35b6103bc6103b7366004613c40565b610b7a565b60405190151581526020016103a0565b600a546103df906001600160a01b031681565b6040516103a09190613c6c565b6103896103fa366004613c80565b610b91565b610407610c7d565b6040516103a09190613c99565b610389610422366004613ce6565b610d03565b6104326301e1338081565b6040519081526020016103a0565b600254610432565b6103bc610456366004613d4f565b610d88565b61046e610469366004613ce6565b610e6e565b604080519915158a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e0830152610100820152610120016103a0565b6103bc6104c2366004613dbb565b610f1f565b610432610fd2565b6103896104dd366004613c80565b61104f565b604051601281526020016103a0565b6104326104ff366004613c80565b6110c0565b6104326110cc565b610432601e5481565b6103896110d6565b61038961052b366004613ce6565b611119565b61038961053e366004613c80565b611196565b600b546103bc90600160a81b900460ff1681565b6104076111f1565b61038961056d366004613e0b565b6111fd565b600b546103bc90600160a01b900460ff1681565b610432601d5481565b61038961059d366004613ce6565b611304565b6103bc6105b0366004613ce6565b611348565b6103896105c3366004613e54565b611355565b6104326105d6366004613ce6565b6001600160a01b031660009081526020819052604090205490565b6104326105ff366004613ce6565b60096020526000908152604090205481565b610389611594565b600f546103df906001600160a01b031681565b61038961063a366004613c80565b6115d5565b61038961064d366004613f44565b61167d565b610389610660366004613ce6565b61185b565b610407611922565b61039361192e565b61043261193d565b61038961068b366004613c80565b611a16565b61043261069e366004613ce6565b611ac1565b610432601f5481565b6103bc6106ba366004613c40565b611b42565b6103896106cd366004613c80565b611b4f565b610407611baa565b6104326106e8366004613ce6565b611bef565b6103896106fb366004613ce6565b611c20565b61038961070e366004613c80565b611cbe565b610432611d22565b610432610729366004613c80565b611d6b565b600e546103df906001600160a01b031681565b610432611e5f565b610389610757366004613fcd565b611ef9565b61043261076a366004613ce6565b6120b9565b61038961077d366004613ce6565b6120ea565b6103bc610790366004613ce6565b61212e565b6104326107a3366004613e54565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6103896107dc366004613c80565b61213b565b6103896107ef366004613ce6565b6121a2565b6103896122bd565b600d546103df906001600160a01b031681565b610389612379565b6104326123ba565b6103896123ff565b61043261271081565b61038961083e366004613c80565b612440565b610393604051806040016040528060058152602001641a9718171960d91b81525081565b3383156109dc57600e5460405163228bfd9f60e01b815260009182916001600160a01b039091169063228bfd9f906108a3908690600401613c6c565b6101206040518083038186803b1580156108bc57600080fd5b505afa1580156108d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f49190614053565b5050505094509450505050600061090c83838961249b565b905080156109d857610996846001600160a01b031663c415b95c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561095057600080fd5b505afa158015610964573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098891906140c3565b6109918361250e565b612573565b60408051838152602081018990529081018290527f692ef79cc704efab4328e6c217b5fb3b1045d0a0314e3e8137029bcb2d59ce4a9060600160405180910390a15b5050505b600e5460405163a066654b60e01b81526001600160a01b038381166004830152602482018790526044820186905260648201859052600092839291169063a066654b906084016040805180830381600087803b158015610a3b57600080fd5b505af1158015610a4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7391906140e0565b90925090506000610a84838861411a565b905081811015610ab457610aaf84610a9c8385614132565b600d546001600160a01b03169190612640565b610adf565b81811115610adf57610adf8430610acb8585614132565b600d546001600160a01b031692919061269b565b50505050505050565b606060038054610af790614149565b80601f0160208091040260200160405190810160405280929190818152602001828054610b2390614149565b8015610b705780601f10610b4557610100808354040283529160200191610b70565b820191906000526020600020905b815481529060010190602001808311610b5357829003601f168201915b5050505050905090565b6000610b873384846126d9565b5060015b92915050565b600a546001600160a01b03163314610bc45760405162461bcd60e51b8152600401610bbb90614184565b60405180910390fd5b604080518082019091526002815261199960f11b602082015281610bfb5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601f5481141560405180604001604052806002815260200161333160f01b81525090610c3b5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601f5460408051918252602082018390527f25c9f41f0fb7a055d44b070262516fbd0111daea3b55d40fae1983827dc99292910160405180910390a1601f55565b600e546040805163088c182960e11b815290516060926001600160a01b0316916311183052916004808301926000929190829003018186803b158015610cc257600080fd5b505afa158015610cd6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cfe91908101906141aa565b905090565b600a546001600160a01b0316331480610d245750610d24335b6019906127fe565b610d405760405162461bcd60e51b8152600401610bbb9061425c565b610d4b601982612820565b604051806040016040528060028152602001610c4d60f21b81525090610d845760405162461bcd60e51b8152600401610bbb9190613bf8565b5050565b6040805180820190915260018152600d60fa1b6020820152600090848314610dc35760405162461bcd60e51b8152600401610bbb9190613bf8565b5060005b84811015610e6257610e17868683818110610de457610de4614282565b9050602002016020810190610df99190613ce6565b858584818110610e0b57610e0b614282565b90506020020135611b42565b604051806040016040528060018152602001601b60f91b81525090610e4f5760405162461bcd60e51b8152600401610bbb9190613bf8565b5080610e5a81614298565b915050610dc7565b50600195945050505050565b600e5460405163228bfd9f60e01b8152600091829182918291829182918291829182916001600160a01b03169063228bfd9f90610eaf908d90600401613c6c565b6101206040518083038186803b158015610ec857600080fd5b505afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f009190614053565b9850985098509850985098509850985098509193959799909294969850565b6000610f2c848484612835565b6001600160a01b038416600090815260016020908152604080832033845290915290205482811015610fb15760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b6064820152608401610bbb565b610fc58533610fc08685614132565b6126d9565b60019150505b9392505050565b600e5460408051632df9eab960e01b815290516000926001600160a01b031691632df9eab9916004808301926020929190829003018186803b15801561101757600080fd5b505afa15801561102b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfe91906142b3565b6002600c5414156110725760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a81b900460ff16156110a15760405162461bcd60e51b8152600401610bbb90614303565b6110af33612916565b612916565b6110b881612957565b506001600c55565b6000610b8b3383612a13565b6000610cfe612ab8565b600a546001600160a01b03163314806110f357506110f333610d1c565b61110f5760405162461bcd60e51b8152600401610bbb9061425c565b611117612b33565b565b600a546001600160a01b0316331480611136575061113633610d1c565b6111525760405162461bcd60e51b8152600401610bbb9061425c565b61115d601982612bea565b60405180604001604052806002815260200161313360f01b81525090610d845760405162461bcd60e51b8152600401610bbb9190613bf8565b6002600c5414156111b95760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a81b900460ff16156111e85760405162461bcd60e51b8152600401610bbb90614303565b6110b881612bff565b6060610cfe601b612c11565b6002600c5414156112205760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a01b900460ff161561124f5760405162461bcd60e51b8152600401610bbb90614325565b600d546001600160a01b031663d505accf336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064810187905260ff8616608482015260a4810185905260c4810184905260e401600060405180830381600087803b1580156112cd57600080fd5b505af11580156112e1573d6000803e3d6000fd5b505050506112ef6110aa3390565b6112f885612c1e565b50506001600c55505050565b600a546001600160a01b0316331480611321575061132133610d1c565b61133d5760405162461bcd60e51b8152600401610bbb9061425c565b61115d601b82612bea565b6000610b8b6019836127fe565b600a546001600160a01b0316331461137f5760405162461bcd60e51b8152600401610bbb90614184565b306001600160a01b0316816001600160a01b03166316f0115b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113c257600080fd5b505afa1580156113d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fa91906140c3565b6001600160a01b03161480156114915750306001600160a01b0316826001600160a01b03166316f0115b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561144e57600080fd5b505afa158015611462573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148691906140c3565b6001600160a01b0316145b60405180604001604052806002815260200161313760f01b815250906114ca5760405162461bcd60e51b8152600401610bbb9190613bf8565b50600e54604051636cb56d1960e01b81526001600160a01b038481166004830152838116602483015290911690636cb56d1990604401600060405180830381600087803b15801561151a57600080fd5b505af115801561152e573d6000803e3d6000fd5b505060405163ce5494bb60e01b81526001600160a01b038516925063ce5494bb915061155e908490600401613c6c565b600060405180830381600087803b15801561157857600080fd5b505af115801561158c573d6000803e3d6000fd5b505050505050565b600a546001600160a01b03163314806115b157506115b133610d1c565b6115cd5760405162461bcd60e51b8152600401610bbb9061425c565b611117612c8c565b600a546001600160a01b031633146115ff5760405162461bcd60e51b8152600401610bbb90614184565b604080518082019091526002815261313160f01b602082015261271082111561163b5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601d5460408051918252602082018390527f905d672396c48f9d1e13c57aec0819f00d39364ab4bf40a46a687aa607b67d81910160405180910390a1601d55565b600554610100900460ff1680611696575060055460ff16155b6116b25760405162461bcd60e51b8152600401610bbb90614345565b600554610100900460ff161580156116d4576005805461ffff19166101011790555b604080518082019091526002815261031360f41b60208201526001600160a01b0384166117145760405162461bcd60e51b8152600401610bbb9190613bf8565b50604080518082019091526002815261031360f41b60208201526001600160a01b0383166117555760405162461bcd60e51b8152600401610bbb9190613bf8565b506117608585612cf1565b61176985612d18565b611771612d97565b600d80546001600160a01b0319166001600160a01b03851617905561179833601990612bea565b60405180604001604052806002815260200161313360f01b815250906117d15760405162461bcd60e51b8152600401610bbb9190613bf8565b506117dd601b33612bea565b60405180604001604052806002815260200161313360f01b815250906118165760405162461bcd60e51b8152600401610bbb9190613bf8565b50600e80546001600160a01b0319166001600160a01b03841617905560c8601d55611388601e556001601f558015611854576005805461ff00191690555b5050505050565b600a546001600160a01b031633146118855760405162461bcd60e51b8152600401610bbb90614184565b604080518082019091526002815261031360f41b60208201526001600160a01b0382166118c55760405162461bcd60e51b8152600401610bbb9190613bf8565b50600f546040516001600160a01b038084169216907fe239974dad08ac696e723caf1886bd0b5afc0870088f9a1266082757f824927690600090a3600f80546001600160a01b0319166001600160a01b0392909216919091179055565b6060610cfe6019612c11565b606060048054610af790614149565b600061194860025490565b15806119595750611957611e5f565b155b156119ef57600d60009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156119ac57600080fd5b505afa1580156119c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e49190614393565b610cfe90600a614494565b6002546119fa611e5f565b611a0c90670de0b6b3a76400006144a3565b610cfe91906144c2565b600a546001600160a01b03163314611a405760405162461bcd60e51b8152600401610bbb90614184565b601e5481141560405180604001604052806002815260200161333160f01b81525090611a7f5760405162461bcd60e51b8152600401610bbb9190613bf8565b50601e5460408051918252602082018390527fafe4d3ceb3295a8d4ef49288a92d32d94e39396e823d414b81caff61b9fc3990910160405180910390a1601e55565b600e54604051639f2b283360e01b81526000916001600160a01b031690639f2b283390611af2908590600401613c6c565b60206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8b91906142b3565b6000610b87338484612835565b6002600c541415611b725760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a01b900460ff1615611ba15760405162461bcd60e51b8152600401610bbb90614325565b6110b881612e45565b600e546040805163b49a60bb60e01b815290516060926001600160a01b03169163b49a60bb916004808301926000929190829003018186803b158015610cc257600080fd5b600e54604051632d90c87b60e21b81526000916001600160a01b03169063b64321ec90611af2908590600401613c6c565b600a546001600160a01b03163314611c4a5760405162461bcd60e51b8152600401610bbb90614184565b6001600160a01b038116611c9c5760405162461bcd60e51b815260206004820152601960248201527870726f706f7365642d676f7665726e6f722d69732d7a65726f60381b6044820152606401610bbb565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b6002600c541415611ce15760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a01b900460ff1615611d105760405162461bcd60e51b8152600401610bbb90614325565b611d1933612916565b6110b881612c1e565b600d546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611d53903090600401613c6c565b60206040518083038186803b15801561101757600080fd5b6000601f54821015604051806040016040528060018152602001603160f81b81525090611dab5760405162461bcd60e51b8152600401610bbb9190613bf8565b506000612710600e60009054906101000a90046001600160a01b03166001600160a01b031663346162d56040518163ffffffff1660e01b815260040160206040518083038186803b158015611dff57600080fd5b505afa158015611e13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3791906142b3565b611e4190856144a3565b611e4b91906144c2565b9050610fcb611e5a8285614132565b61250e565b6000611e69611d22565b600e60009054906101000a90046001600160a01b03166001600160a01b031663fc7b9c186040518163ffffffff1660e01b815260040160206040518083038186803b158015611eb757600080fd5b505afa158015611ecb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eef91906142b3565b610cfe919061411a565b83421115611f495760405162461bcd60e51b815260206004820152601d60248201527f45524332305065726d69743a206578706972656420646561646c696e650000006044820152606401610bbb565b6001600160a01b0387811660008181526009602090815260408083205481517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98185015280830195909552948b166060850152608084018a905260a0840185905260c08085018a90528151808603909101815260e09094019052825192019190912090611fd4612ab8565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050600061201a82888888612e57565b90508a6001600160a01b0316816001600160a01b03161461207d5760405162461bcd60e51b815260206004820152601e60248201527f45524332305065726d69743a20696e76616c6964207369676e617475726500006044820152606401610bbb565b61208884600161411a565b6001600160a01b038c166000908152600960205260409020556120ac8b8b8b6126d9565b5050505050505050505050565b600e54604051636a9eee1360e11b81526000916001600160a01b03169063d53ddc2690611af2908590600401613c6c565b600a546001600160a01b0316331480612107575061210733610d1c565b6121235760405162461bcd60e51b8152600401610bbb9061425c565b610d4b601b82612820565b6000610b8b601b836127fe565b801561219f57600e546001600160a01b0316637f13086e33836040518363ffffffff1660e01b81526004016121719291906144e4565b600060405180830381600087803b15801561218b57600080fd5b505af1158015611854573d6000803e3d6000fd5b50565b600a546001600160a01b03163314806121bf57506121bf33610d1c565b6121db5760405162461bcd60e51b8152600401610bbb9061425c565b600d546040805180820190915260018152600760fb1b6020820152906001600160a01b03838116911614156122235760405162461bcd60e51b8152600401610bbb9190613bf8565b50600a546040516370a0823160e01b815261219f916001600160a01b0390811691908416906370a082319061225c903090600401613c6c565b60206040518083038186803b15801561227457600080fd5b505afa158015612288573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ac91906142b3565b6001600160a01b0384169190612640565b600b546001600160a01b031633146123135760405162461bcd60e51b81526020600482015260196024820152783737ba16ba343296b83937b837b9b2b216b3b7bb32b93737b960391b6044820152606401610bbb565b600b54600a546040516001600160a01b0392831692909116907fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d090600090a3600b8054600a80546001600160a01b03199081166001600160a01b03841617909155169055565b600a546001600160a01b0316331480612396575061239633610d1c565b6123b25760405162461bcd60e51b8152600401610bbb9061425c565b611117612fe8565b600e5460408051631f8f738360e31b815290516000926001600160a01b03169163fc7b9c18916004808301926020929190829003018186803b15801561101757600080fd5b600a546001600160a01b031633148061241c575061241c33610d1c565b6124385760405162461bcd60e51b8152600401610bbb9061425c565b61111761304e565b6002600c5414156124635760405162461bcd60e51b8152600401610bbb906142cc565b6002600c55600b54600160a81b900460ff16156124925760405162461bcd60e51b8152600401610bbb90614303565b6110af336130ca565b60006124ad6301e133806127106144a3565b836124b88642614132565b601d546124c591906144a3565b6124cf91906144a3565b6124d991906144c2565b90506000612710601e54846124ee91906144a3565b6124f891906144c2565b905080821115612506578091505b509392505050565b60008061251961193d565b61252b84670de0b6b3a76400006144a3565b61253591906144c2565b9050670de0b6b3a764000061254861193d565b61255290836144a3565b61255c91906144c2565b83116125685780610fcb565b610fcb81600161411a565b6001600160a01b0382166125c95760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610bbb565b80600260008282546125db919061411a565b90915550506001600160a01b0382166000908152602081905260408120805483929061260890849061411a565b90915550506040518181526001600160a01b0383169060009060008051602061454b8339815191529060200160405180910390a35050565b6126968363a9059cbb60e01b848460405160240161265f9291906144e4565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261310b565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526126d39085906323b872dd60e01b9060840161265f565b50505050565b6001600160a01b03831661273b5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610bbb565b6001600160a01b03821661279c5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610bbb565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b03811660009081526001830160205260408120541515610fcb565b6000610fcb836001600160a01b0384166131dd565b600f546001600160a01b03161561290b57600f5460405163632447c960e01b81526001600160a01b039091169063632447c990612876908690600401613c6c565b600060405180830381600087803b15801561289057600080fd5b505af11580156128a4573d6000803e3d6000fd5b5050600f5460405163632447c960e01b81526001600160a01b03909116925063632447c991506128d8908590600401613c6c565b600060405180830381600087803b1580156128f257600080fd5b505af1158015612906573d6000803e3d6000fd5b505050505b6126968383836132d0565b600f546001600160a01b03161561219f57600f5460405163632447c960e01b81526001600160a01b039091169063632447c990612171908490600401613c6c565b6040805180820190915260018152601960f91b60208201528161298d5760405162461bcd60e51b8152600401610bbb9190613bf8565b5060008061299a83613496565b9150915080156129bf5760006129af8361250e565b9050838110156129bd578093505b505b6129c93384613543565b6129d282613680565b50604080518481526020810184905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a2505050565b600e5460405163228bfd9f60e01b8152600091829182916001600160a01b03169063228bfd9f90612a48908890600401613c6c565b6101206040518083038186803b158015612a6157600080fd5b505afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190614053565b5050505094509450505050612aaf82828661249b565b95945050505050565b6000600854461415612acb575060065490565b6007546040805180820190915260018152603160f81b602090910152610cfe907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f907fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc661369d565b600b54600160a01b900460ff16612b795760405162461bcd60e51b815260206004820152600a6024820152691b9bdd0b5c185d5cd95960b21b6044820152606401610bbb565b600b54600160a81b900460ff1615612ba35760405162461bcd60e51b8152600401610bbb90614303565b600b805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051612be09190613c6c565b60405180910390a1565b6000610fcb836001600160a01b0384166136e6565b612c08336130ca565b61219f81612957565b60606000610fcb83613735565b6000612c2982611d6b565b9050612c4333600d546001600160a01b031690308561269b565b612c4d3382612573565b604080518281526020810184905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a25050565b600b54600160a01b900460ff1615612cb65760405162461bcd60e51b8152600401610bbb90614325565b600b805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612bd33390565b8151612d04906003906020850190613b10565b508051612696906004906020840190613b10565b80516020808301919091206007819055466008556040805180820190915260018152603160f81b920191909152612d91907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f907fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc661369d565b60065550565b600554610100900460ff1680612db0575060055460ff16155b612dcc5760405162461bcd60e51b8152600401610bbb90614345565b600554610100900460ff16158015612dee576005805461ffff19166101011790555b600a80546001600160a01b0319163390811790915560405181906000907fd4459d5b8b913cab0244230fd9b1c08b6ceace7fe9230e60d0f74cbffdf849d0908290a350801561219f576005805461ff001916905550565b612e4e336130ca565b61219f81612c1e565b60006fa2a8918ca85bafe22016d0b997e4df60600160ff1b03821115612eca5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610bbb565b8360ff16601b1480612edf57508360ff16601c145b612f365760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610bbb565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa158015612f8a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612aaf5760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610bbb565b600b54600160a81b900460ff16156130125760405162461bcd60e51b8152600401610bbb90614303565b600b805461ffff60a01b191661010160a01b1790557f28b4c24cb1012c094cd2f59f98e89d791973295f8fda6eaa118022d6d318960a33612bd3565b600b54600160a81b900460ff166130965760405162461bcd60e51b815260206004820152600c60248201526b3737ba16b9b43aba3237bbb760a11b6044820152606401610bbb565b600b805460ff60a81b191690557fece7583a70a505ef0e36d4dec768f5ae597713e09c26011022599ee01abdabfc33612bd3565b600f546001600160a01b03161561219f57600f5460405163d279c19160e01b81526001600160a01b039091169063d279c19190612171908490600401613c6c565b6000613160826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166137919092919063ffffffff16565b805190915015612696578080602001905181019061317e91906144fd565b6126965760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610bbb565b600081815260018301602052604081205480156132c6576000613201600183614132565b855490915060009061321590600190614132565b905081811461327a57600086600001828154811061323557613235614282565b906000526020600020015490508087600001848154811061325857613258614282565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061328b5761328b614518565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610b8b565b6000915050610b8b565b6001600160a01b0383166133345760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610bbb565b6001600160a01b0382166133965760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610bbb565b6001600160a01b0383166000908152602081905260409020548181101561340e5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610bbb565b6134188282614132565b6001600160a01b03808616600090815260208190526040808220939093559085168152908120805484929061344e90849061411a565b92505081905550826001600160a01b0316846001600160a01b031660008051602061454b8339815191528460405161348891815260200190565b60405180910390a350505050565b6000806000670de0b6b3a76400006134ac61193d565b6134b690866144a3565b6134c091906144c2565b905060006134cc611d22565b905081935080821115613505576134eb6134e68284614132565b6137a8565b6134f3611d22565b90508082111561350557809350600192505b6040805180820190915260018152603160f81b60208201528461353b5760405162461bcd60e51b8152600401610bbb9190613bf8565b505050915091565b6001600160a01b0382166135a35760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610bbb565b6001600160a01b038216600090815260208190526040902054818110156136175760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610bbb565b6136218282614132565b6001600160a01b0384166000908152602081905260408120919091556002805484929061364f908490614132565b90915550506040518281526000906001600160a01b0385169060008051602061454b833981519152906020016127f1565b600061369933600d546001600160a01b03169084612640565b5090565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600081815260018301602052604081205461372d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610b8b565b506000610b8b565b60608160000180548060200260200160405190810160405280929190818152602001828054801561378557602002820191906000526020600020905b815481526020019060010190808311613771575b50505050509050919050565b60606137a084846000856139af565b949350505050565b6000806000806000806137b9610c7d565b805190915060005b818110156139a45760006137d5858b614132565b905060008483815181106137eb576137eb614282565b6020908102919091010151600e54604051639f2b283360e01b81529192506001600160a01b031690639f2b283390613827908490600401613c6c565b60206040518083038186803b15801561383f57600080fd5b505afa158015613853573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061387791906142b3565b995089613885575050613992565b89821115613891578991505b613899611d22565b604051632e1a7d4d60e01b8152600481018490529098506001600160a01b03821690632e1a7d4d90602401600060405180830381600087803b1580156138de57600080fd5b505af19250505080156138ef575060015b6138fa575050613992565b613902611d22565b985061390e888a614132565b600e54604051632fb9ba3160e01b81529198506001600160a01b031690632fb9ba31906139419084908b906004016144e4565b600060405180830381600087803b15801561395b57600080fd5b505af115801561396f573d6000803e3d6000fd5b50505050868661397f919061411a565b95508a861061398f5750506139a4565b50505b8061399c81614298565b9150506137c1565b505050505050505050565b606082471015613a105760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610bbb565b843b613a5e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bbb565b600080866001600160a01b03168587604051613a7a919061452e565b60006040518083038185875af1925050503d8060008114613ab7576040519150601f19603f3d011682016040523d82523d6000602084013e613abc565b606091505b5091509150613acc828286613ad7565b979650505050505050565b60608315613ae6575081610fcb565b825115613af65782518084602001fd5b8160405162461bcd60e51b8152600401610bbb9190613bf8565b828054613b1c90614149565b90600052602060002090601f016020900481019282613b3e5760008555613b84565b82601f10613b5757805160ff1916838001178555613b84565b82800160010185558215613b84579182015b82811115613b84578251825591602001919060010190613b69565b506136999291505b808211156136995760008155600101613b8c565b600080600060608486031215613bb557600080fd5b505081359360208301359350604090920135919050565b60005b83811015613be7578181015183820152602001613bcf565b838111156126d35750506000910152565b6020815260008251806020840152613c17816040850160208701613bcc565b601f01601f19169190910160400192915050565b6001600160a01b038116811461219f57600080fd5b60008060408385031215613c5357600080fd5b8235613c5e81613c2b565b946020939093013593505050565b6001600160a01b0391909116815260200190565b600060208284031215613c9257600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015613cda5783516001600160a01b031683529284019291840191600101613cb5565b50909695505050505050565b600060208284031215613cf857600080fd5b8135610fcb81613c2b565b60008083601f840112613d1557600080fd5b50813567ffffffffffffffff811115613d2d57600080fd5b6020830191508360208260051b8501011115613d4857600080fd5b9250929050565b60008060008060408587031215613d6557600080fd5b843567ffffffffffffffff80821115613d7d57600080fd5b613d8988838901613d03565b90965094506020870135915080821115613da257600080fd5b50613daf87828801613d03565b95989497509550505050565b600080600060608486031215613dd057600080fd5b8335613ddb81613c2b565b92506020840135613deb81613c2b565b929592945050506040919091013590565b60ff8116811461219f57600080fd5b600080600080600060a08688031215613e2357600080fd5b85359450602086013593506040860135613e3c81613dfc565b94979396509394606081013594506080013592915050565b60008060408385031215613e6757600080fd5b8235613e7281613c2b565b91506020830135613e8281613c2b565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613ecc57613ecc613e8d565b604052919050565b600082601f830112613ee557600080fd5b813567ffffffffffffffff811115613eff57613eff613e8d565b613f12601f8201601f1916602001613ea3565b818152846020838601011115613f2757600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215613f5a57600080fd5b843567ffffffffffffffff80821115613f7257600080fd5b613f7e88838901613ed4565b95506020870135915080821115613f9457600080fd5b50613fa187828801613ed4565b9350506040850135613fb281613c2b565b91506060850135613fc281613c2b565b939692955090935050565b600080600080600080600060e0888a031215613fe857600080fd5b8735613ff381613c2b565b9650602088013561400381613c2b565b95506040880135945060608801359350608088013561402181613dfc565b9699959850939692959460a0840135945060c09093013592915050565b8051801515811461404e57600080fd5b919050565b60008060008060008060008060006101208a8c03121561407257600080fd5b61407b8a61403e565b985060208a0151975060408a0151965060608a0151955060808a0151945060a08a0151935060c08a0151925060e08a015191506101008a015190509295985092959850929598565b6000602082840312156140d557600080fd5b8151610fcb81613c2b565b600080604083850312156140f357600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b6000821982111561412d5761412d614104565b500190565b60008282101561414457614144614104565b500390565b600181811c9082168061415d57607f821691505b6020821081141561417e57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b3737ba16b3b7bb32b93737b960a11b604082015260600190565b600060208083850312156141bd57600080fd5b825167ffffffffffffffff808211156141d557600080fd5b818501915085601f8301126141e957600080fd5b8151818111156141fb576141fb613e8d565b8060051b915061420c848301613ea3565b818152918301840191848101908884111561422657600080fd5b938501935b83851015614250578451925061424083613c2b565b828252938501939085019061422b565b98975050505050505050565b6020808252600c908201526b3737ba16b096b5b2b2b832b960a11b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006000198214156142ac576142ac614104565b5060010190565b6000602082840312156142c557600080fd5b5051919050565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526008908201526739b43aba3237bbb760c11b604082015260600190565b6020808252600690820152651c185d5cd95960d21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000602082840312156143a557600080fd5b8151610fcb81613dfc565b600181815b808511156143eb5781600019048211156143d1576143d1614104565b808516156143de57918102915b93841c93908002906143b5565b509250929050565b60008261440257506001610b8b565b8161440f57506000610b8b565b8160018114614425576002811461442f5761444b565b6001915050610b8b565b60ff84111561444057614440614104565b50506001821b610b8b565b5060208310610133831016604e8410600b841016171561446e575081810a610b8b565b61447883836143b0565b806000190482111561448c5761448c614104565b029392505050565b6000610fcb60ff8416836143f3565b60008160001904831182151516156144bd576144bd614104565b500290565b6000826144df57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03929092168252602082015260400190565b60006020828403121561450f57600080fd5b610fcb8261403e565b634e487b7160e01b600052603160045260246000fd5b60008251614540818460208701613bcc565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220e86c694a8614e406b22780f263b0ec173754481a0904cd83ca58cf5b7c14538064736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b56657370657220706f6f6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000576506f6f6c000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): Vesper pool
Arg [1] : _symbol (string): vPool
Arg [2] : _token (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [4] : 56657370657220706f6f6c000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 76506f6f6c000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 29 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.