Overview
GLMR Balance
GLMR Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Unbonded | 2252820 | 896 days ago | IN | 0 GLMR | 0.002841 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Lido
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma abicoder v2; import "IERC20.sol"; import "SafeCast.sol"; import "Initializable.sol"; import "IOracleMaster.sol"; import "ILedgerFactory.sol"; import "ILedger.sol"; import "IController.sol"; import "IAuthManager.sol"; import "IWithdrawal.sol"; import "stKSM.sol"; contract Lido is stKSM, Initializable { using SafeCast for uint256; // Records a deposit made by a user event Deposited(address indexed sender, uint256 amount); // Created redeem order event Redeemed(address indexed receiver, uint256 amount); // Claimed vKSM tokens back event Claimed(address indexed receiver, uint256 amount); // Fee was updated event FeeSet(uint16 fee, uint16 feeOperatorsBP, uint16 feeTreasuryBP, uint16 feeDevelopersBP); // Rewards distributed event Rewards(address ledger, uint256 rewards, uint256 balance); // Losses distributed event Losses(address ledger, uint256 losses, uint256 balance); // Added new ledger event LedgerAdd( address addr, bytes32 stashAccount, bytes32 controllerAccount ); // Ledger removed event LedgerRemove( address addr ); // Ledger disabled event LedgerDisable( address addr ); // Ledger paused event LedgerPaused( address addr ); // Ledger resumed event LedgerResumed( address addr ); // Referral program event Referral( address userAddr, address referralAddr, uint256 amount, uint256 shares ); // sum of all deposits and rewards uint256 public fundRaisedBalance; // haven't executed buffrered deposits: // // this is the amount of funds that must either sent to the ledgers // or rebalanced to buffered redeems uint256 public bufferedDeposits; // haven't executed buffrered redeems: // this is the amount of funds that should be sent to the WITHDRAWAL contract uint256 public bufferedRedeems; // this is the active stake on the ledger = [ledgerBorrow] - unbonded funds - free funds mapping(address => uint256) public ledgerStake; // this is the total amount of funds in the ledger = active stake + unbonded funds + free funds mapping(address => uint256) public ledgerBorrow; // Disabled ledgers address[] private disabledLedgers; // Enabled ledgers address[] private enabledLedgers; // Cap for deposits for v1 uint256 public depositCap; // vKSM precompile IERC20 private VKSM; // controller address private CONTROLLER; // auth manager contract address address public AUTH_MANAGER; // Maximum number of ledgers uint256 private MAX_LEDGERS_AMOUNT; // oracle master contract address public ORACLE_MASTER; // relay spec Types.RelaySpec private RELAY_SPEC; // developers fund address private developers; // treasury fund address private treasury; // ledger beacon address public LEDGER_BEACON; // ledger factory address private LEDGER_FACTORY; // withdrawal contract address private WITHDRAWAL; // Max allowable difference for oracle reports uint128 public MAX_ALLOWABLE_DIFFERENCE; // Ledger address by stash account id mapping(bytes32 => address) private ledgerByStash; // Map to check ledger existence by address mapping(address => bool) private ledgerByAddress; // Map to check ledger paused to redeem state mapping(address => bool) private pausedledgers; /* fee interest in basis points. It's packed uint256 consist of three uint16 (total_fee, treasury_fee, developers_fee). where total_fee = treasury_fee + developers_fee + 3000 (3% operators fee) */ Types.Fee private FEE; // default interest value in base points. uint16 internal constant DEFAULT_DEVELOPERS_FEE = 200; uint16 internal constant DEFAULT_OPERATORS_FEE = 0; uint16 internal constant DEFAULT_TREASURY_FEE = 800; // Missing member index uint256 internal constant MEMBER_NOT_FOUND = type(uint256).max; // Spec manager role bytes32 internal constant ROLE_SPEC_MANAGER = keccak256("ROLE_SPEC_MANAGER"); // Beacon manager role bytes32 internal constant ROLE_BEACON_MANAGER = keccak256("ROLE_BEACON_MANAGER"); // Pause manager role bytes32 internal constant ROLE_PAUSE_MANAGER = keccak256("ROLE_PAUSE_MANAGER"); // Fee manager role bytes32 internal constant ROLE_FEE_MANAGER = keccak256("ROLE_FEE_MANAGER"); // Ledger manager role bytes32 internal constant ROLE_LEDGER_MANAGER = keccak256("ROLE_LEDGER_MANAGER"); // Stake manager role bytes32 internal constant ROLE_STAKE_MANAGER = keccak256("ROLE_STAKE_MANAGER"); // Treasury manager role bytes32 internal constant ROLE_TREASURY = keccak256("ROLE_SET_TREASURY"); // Developers address change role bytes32 internal constant ROLE_DEVELOPERS = keccak256("ROLE_SET_DEVELOPERS"); // Token name string internal _name; // Token symbol string internal _symbol; // Token decimals uint8 internal _decimals; // Allow function calls only from member with specific role modifier auth(bytes32 role) { require(IAuthManager(AUTH_MANAGER).has(role, msg.sender), "LIDO: UNAUTHORIZED"); _; } /** * @return the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @return the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @return the number of decimals for getting user representation of a token amount. */ function decimals() public view returns (uint8) { return _decimals; } /** * @notice setting token parameters */ // NOTE: function was removed from Lido, because it can be called only once to set parameters and after that // it is unnecessary in the code. It was removed to decrease contract bytecode size // function setTokenInfo(string memory __name, string memory __symbol, uint8 __decimals) external { // require(bytes(__name).length > 0, "LIDO: EMPTY_NAME"); // require(bytes(__symbol).length > 0, "LIDO: EMPTY_SYMBOL"); // require(__decimals > 0, "LIDO: ZERO_DECIMALS"); // require(bytes(_name).length == 0, "LIDO: NAME_SETTED"); // _name = __name; // _symbol = __symbol; // _decimals = __decimals; // } /** * @notice Initialize lido contract. * @param _authManager - auth manager contract address * @param _vKSM - vKSM contract address * @param _controller - relay controller address * @param _developers - devs address * @param _treasury - treasury address * @param _oracleMaster - oracle master address * @param _withdrawal - withdrawal address * @param _depositCap - cap for deposits * @param _maxAllowableDifference - max allowable difference for oracle reports */ function initialize( address _authManager, address _vKSM, address _controller, address _developers, address _treasury, address _oracleMaster, address _withdrawal, uint256 _depositCap, uint128 _maxAllowableDifference ) external initializer { require(_depositCap > 0, "LIDO: ZERO_CAP"); require(_vKSM != address(0), "LIDO: INCORRECT_VKSM_ADDRESS"); require(_oracleMaster != address(0), "LIDO: INCORRECT_ORACLE_MASTER_ADDRESS"); require(_withdrawal != address(0), "LIDO: INCORRECT_WITHDRAWAL_ADDRESS"); require(_authManager != address(0), "LIDO: INCORRECT_AUTHMANAGER_ADDRESS"); require(_controller != address(0), "LIDO: INCORRECT_CONTROLLER_ADDRESS"); VKSM = IERC20(_vKSM); CONTROLLER = _controller; AUTH_MANAGER = _authManager; depositCap = _depositCap; MAX_LEDGERS_AMOUNT = 200; Types.Fee memory _fee; _fee.total = DEFAULT_OPERATORS_FEE + DEFAULT_DEVELOPERS_FEE + DEFAULT_TREASURY_FEE; _fee.operators = DEFAULT_OPERATORS_FEE; _fee.developers = DEFAULT_DEVELOPERS_FEE; _fee.treasury = DEFAULT_TREASURY_FEE; FEE = _fee; treasury = _treasury; developers =_developers; ORACLE_MASTER = _oracleMaster; IOracleMaster(ORACLE_MASTER).setLido(address(this)); WITHDRAWAL = _withdrawal; IWithdrawal(WITHDRAWAL).setStKSM(address(this)); MAX_ALLOWABLE_DIFFERENCE = _maxAllowableDifference; } /** * @notice Set treasury address to '_treasury' */ function setTreasury(address _treasury) external auth(ROLE_TREASURY) { require(_treasury != address(0), "LIDO: INCORRECT_TREASURY_ADDRESS"); treasury = _treasury; } /** * @notice Set deposit cap to new value */ function setDepositCap(uint256 _depositCap) external auth(ROLE_PAUSE_MANAGER) { require(_depositCap > 0, "LIDO: INCORRECT_NEW_CAP"); depositCap = _depositCap; } /** * @notice Set ledger beacon address to '_ledgerBeacon' */ function setLedgerBeacon(address _ledgerBeacon) external auth(ROLE_BEACON_MANAGER) { require(_ledgerBeacon != address(0), "LIDO: INCORRECT_BEACON_ADDRESS"); LEDGER_BEACON = _ledgerBeacon; } function setMaxAllowableDifference(uint128 _maxAllowableDifference) external auth(ROLE_BEACON_MANAGER) { require(_maxAllowableDifference > 0, "LIDO: INCORRECT_MAX_ALLOWABLE_DIFFERENCE"); MAX_ALLOWABLE_DIFFERENCE = _maxAllowableDifference; } /** * @notice Set ledger factory address to '_ledgerFactory' */ function setLedgerFactory(address _ledgerFactory) external auth(ROLE_BEACON_MANAGER) { require(_ledgerFactory != address(0), "LIDO: INCORRECT_FACTORY_ADDRESS"); LEDGER_FACTORY = _ledgerFactory; } /** * @notice Set developers address to '_developers' */ function setDevelopers(address _developers) external auth(ROLE_DEVELOPERS) { require(_developers != address(0), "LIDO: INCORRECT_DEVELOPERS_ADDRESS"); developers = _developers; } /** * @notice Set relay chain spec, allowed to call only by ROLE_SPEC_MANAGER * @dev if some params are changed function will iterate over oracles and ledgers, be careful * @param _relaySpec - new relaychain spec */ function setRelaySpec(Types.RelaySpec calldata _relaySpec) external auth(ROLE_SPEC_MANAGER) { require(_relaySpec.maxValidatorsPerLedger > 0, "LIDO: BAD_MAX_VALIDATORS_PER_LEDGER"); require(_relaySpec.maxUnlockingChunks > 0, "LIDO: BAD_MAX_UNLOCKING_CHUNKS"); RELAY_SPEC = _relaySpec; _updateLedgerRelaySpecs(_relaySpec.minNominatorBalance, _relaySpec.ledgerMinimumActiveBalance, _relaySpec.maxUnlockingChunks); } /** * @notice Set new lido fee, allowed to call only by ROLE_FEE_MANAGER * @param _feeOperators - Operators percentage in basis points. It's always 3% * @param _feeTreasury - Treasury fund percentage in basis points * @param _feeDevelopers - Developers percentage in basis points */ function setFee(uint16 _feeOperators, uint16 _feeTreasury, uint16 _feeDevelopers) external auth(ROLE_FEE_MANAGER) { Types.Fee memory _fee; _fee.total = _feeTreasury + _feeOperators + _feeDevelopers; require(_fee.total <= 10000 && (_feeTreasury > 0 || _feeDevelopers > 0) && _feeOperators < 10000, "LIDO: FEE_DONT_ADD_UP"); emit FeeSet(_fee.total, _feeOperators, _feeTreasury, _feeDevelopers); _fee.developers = _feeDevelopers; _fee.operators = _feeOperators; _fee.treasury = _feeTreasury; FEE = _fee; } /** * @notice Return unbonded tokens amount for user * @param _holder - user account for whom need to calculate unbonding * @return waiting - amount of tokens which are not unbonded yet * @return unbonded - amount of token which unbonded and ready to claim */ function getUnbonded(address _holder) external view returns (uint256 waiting, uint256 unbonded) { return IWithdrawal(WITHDRAWAL).getRedeemStatus(_holder); } /** * @notice Return relay chain stash account addresses * @return Array of bytes32 relaychain stash accounts */ function getStashAccounts() public view returns (bytes32[] memory) { bytes32[] memory _stashes = new bytes32[](enabledLedgers.length + disabledLedgers.length); for (uint i = 0; i < enabledLedgers.length + disabledLedgers.length; i++) { address ledgerAddr = i < enabledLedgers.length ? enabledLedgers[i] : disabledLedgers[i - enabledLedgers.length]; _stashes[i] = bytes32(ILedger(ledgerAddr).stashAccount()); } return _stashes; } /** * @notice Return ledger contract addresses * @dev Each ledger contract linked with single stash account on the relaychain side * @return Array of ledger contract addresses */ function getLedgerAddresses() public view returns (address[] memory) { address[] memory _ledgers = new address[](enabledLedgers.length + disabledLedgers.length); for (uint i = 0; i < enabledLedgers.length + disabledLedgers.length; i++) { _ledgers[i] = i < enabledLedgers.length ? enabledLedgers[i] : disabledLedgers[i - enabledLedgers.length]; } return _ledgers; } /** * @notice Return ledger address by stash account id * @dev If ledger not found function returns ZERO address * @param _stashAccount - relaychain stash account id * @return Linked ledger contract address */ function findLedger(bytes32 _stashAccount) external view returns (address) { return ledgerByStash[_stashAccount]; } /** * @notice Stop pool routine operations (deposit, redeem, claimUnbonded), * allowed to call only by ROLE_PAUSE_MANAGER */ function pause() external auth(ROLE_PAUSE_MANAGER) { _pause(); } /** * @notice Resume pool routine operations (deposit, redeem, claimUnbonded), * allowed to call only by ROLE_PAUSE_MANAGER */ function resume() external auth(ROLE_PAUSE_MANAGER) { _unpause(); } /** * @notice Add new ledger, allowed to call only by ROLE_LEDGER_MANAGER * @dev That function deploys new ledger for provided stash account * Also method triggers rebalancing stakes accross ledgers, recommended to carefully calculate share value to avoid significant rebalancing. * @param _stashAccount - relaychain stash account id * @param _controllerAccount - controller account id for given stash * @return created ledger address */ function addLedger( bytes32 _stashAccount, bytes32 _controllerAccount, uint16 _index ) external auth(ROLE_LEDGER_MANAGER) returns(address) { require(LEDGER_BEACON != address(0), "LIDO: UNSPECIFIED_LEDGER_BEACON"); require(LEDGER_FACTORY != address(0), "LIDO: UNSPECIFIED_LEDGER_FACTORY"); require(ORACLE_MASTER != address(0), "LIDO: NO_ORACLE_MASTER"); require(enabledLedgers.length + disabledLedgers.length < MAX_LEDGERS_AMOUNT, "LIDO: LEDGERS_POOL_LIMIT"); require(ledgerByStash[_stashAccount] == address(0), "LIDO: STASH_ALREADY_EXISTS"); address ledger = ILedgerFactory(LEDGER_FACTORY).createLedger( _stashAccount, _controllerAccount, address(VKSM), CONTROLLER, RELAY_SPEC.minNominatorBalance, RELAY_SPEC.ledgerMinimumActiveBalance, RELAY_SPEC.maxUnlockingChunks ); enabledLedgers.push(ledger); ledgerByStash[_stashAccount] = ledger; ledgerByAddress[ledger] = true; IOracleMaster(ORACLE_MASTER).addLedger(ledger); IController(CONTROLLER).newSubAccount(_index, _stashAccount, ledger); emit LedgerAdd(ledger, _stashAccount, _controllerAccount); return ledger; } /** * @notice Disable ledger, allowed to call only by ROLE_LEDGER_MANAGER * @dev That method put ledger to "draining" mode, after ledger drained it can be removed * @param _ledgerAddress - target ledger address */ function disableLedger(address _ledgerAddress) external auth(ROLE_LEDGER_MANAGER) { _disableLedger(_ledgerAddress); } /** * @notice Disable ledger and pause all redeems for that ledger, allowed to call only by ROLE_LEDGER_MANAGER * @dev That method pause all stake changes for ledger * @param _ledgerAddress - target ledger address */ function emergencyPauseLedger(address _ledgerAddress) external auth(ROLE_LEDGER_MANAGER) { _disableLedger(_ledgerAddress); pausedledgers[_ledgerAddress] = true; emit LedgerPaused(_ledgerAddress); } /** * @notice Allow redeems from paused ledger, allowed to call only by ROLE_LEDGER_MANAGER * @param _ledgerAddress - target ledger address */ function resumeLedger(address _ledgerAddress) external auth(ROLE_LEDGER_MANAGER) { require(pausedledgers[_ledgerAddress], "LIDO: LEDGER_NOT_PAUSED"); delete pausedledgers[_ledgerAddress]; emit LedgerResumed(_ledgerAddress); } /** * @notice Remove ledger, allowed to call only by ROLE_LEDGER_MANAGER * @dev That method cannot be executed for running ledger, so need to drain funds * @param _ledgerAddress - target ledger address */ function removeLedger(address _ledgerAddress) external auth(ROLE_LEDGER_MANAGER) { require(ledgerByAddress[_ledgerAddress], "LIDO: LEDGER_NOT_FOUND"); require(ledgerStake[_ledgerAddress] == 0, "LIDO: LEDGER_HAS_NON_ZERO_STAKE"); // uint256 ledgerIdx = _findDisabledLedger(_ledgerAddress); uint256 ledgerIdx = _findLedger(_ledgerAddress, false); require(ledgerIdx != type(uint256).max, "LIDO: LEDGER_NOT_DISABLED"); ILedger ledger = ILedger(_ledgerAddress); require(ledger.isEmpty(), "LIDO: LEDGER_IS_NOT_EMPTY"); address lastLedger = disabledLedgers[disabledLedgers.length - 1]; disabledLedgers[ledgerIdx] = lastLedger; disabledLedgers.pop(); delete ledgerByAddress[_ledgerAddress]; delete ledgerByStash[ledger.stashAccount()]; if (pausedledgers[_ledgerAddress]) { delete pausedledgers[_ledgerAddress]; } IOracleMaster(ORACLE_MASTER).removeLedger(_ledgerAddress); IController(CONTROLLER).deleteSubAccount(_ledgerAddress); emit LedgerRemove(_ledgerAddress); } /** * @notice Nominate on behalf of gived array of stash accounts, allowed to call only by ROLE_STAKE_MANAGER * @dev Method spawns xcm call to relaychain * @param _stashAccounts - target stash accounts id * @param _validators - validators set to be nominated */ function nominateBatch(bytes32[] calldata _stashAccounts, bytes32[][] calldata _validators) external auth(ROLE_STAKE_MANAGER) { require(_stashAccounts.length == _validators.length, "LIDO: INCORRECT_INPUT"); for (uint256 i = 0; i < _stashAccounts.length; ++i) { require(ledgerByStash[_stashAccounts[i]] != address(0), "LIDO: UNKNOWN_STASH_ACCOUNT"); require(_validators[i].length <= RELAY_SPEC.maxValidatorsPerLedger, "LIDO: VALIDATORS_AMOUNT_TOO_BIG"); ILedger(ledgerByStash[_stashAccounts[i]]).nominate(_validators[i]); } } function deposit(uint256 _amount) external returns (uint256) { return _deposit(_amount); } function deposit(uint256 _amount, address _referral) external returns (uint256) { uint256 shares = _deposit(_amount); emit Referral(msg.sender, _referral, _amount, shares); return shares; } /** * @notice Deposit vKSM tokens to the pool and recieve stKSM(liquid staked tokens) instead. User should approve tokens before executing this call. * @dev Method accoumulate vKSMs on contract * @param _amount - amount of vKSM tokens to be deposited */ function _deposit(uint256 _amount) internal whenNotPaused returns (uint256) { require(fundRaisedBalance + _amount < depositCap, "LIDO: DEPOSITS_EXCEED_CAP"); VKSM.transferFrom(msg.sender, address(this), _amount); require(_amount != 0, "LIDO: ZERO_DEPOSIT"); uint256 shares = getSharesByPooledKSM(_amount); if (shares == 0) { // totalPooledKSM is 0: either the first-ever deposit or complete slashing // assume that shares correspond to KSM as 1-to-1 shares = _amount; } fundRaisedBalance += _amount; bufferedDeposits += _amount; _mintShares(msg.sender, shares); _emitTransferAfterMintingShares(msg.sender, shares); emit Deposited(msg.sender, _amount); return shares; } /** * @notice Create request to redeem vKSM in exchange of stKSM. stKSM will be instantly burned and created claim order, (see `getUnbonded` method). User can have up to 20 redeem requests in parallel. * @param _amount - amount of stKSM tokens to be redeemed */ function redeem(uint256 _amount) external whenNotPaused { uint256 _shares = getSharesByPooledKSM(_amount); require(_shares > 0, "LIDO: AMOUNT_TOO_LOW"); require(_shares <= _sharesOf(msg.sender), "LIDO: REDEEM_AMOUNT_EXCEEDS_BALANCE"); _burnShares(msg.sender, _shares); fundRaisedBalance -= _amount; bufferedRedeems += _amount; IWithdrawal(WITHDRAWAL).redeem(msg.sender, _amount); // emit event about burning (compatible with ERC20) emit Transfer(msg.sender, address(0), _amount); // lido event about redeemed emit Redeemed(msg.sender, _amount); } /** * @notice Claim all unbonded tokens at this point of time. Executed redeem requests will be removed and approproate amount of vKSM transferred to calling account. */ function claimUnbonded() external whenNotPaused { uint256 amount = IWithdrawal(WITHDRAWAL).claim(msg.sender); emit Claimed(msg.sender, amount); } /** * @notice Distribute rewards earned by ledger, allowed to call only by ledger */ function distributeRewards(uint256 _totalRewards, uint256 _ledgerBalance) external { require(ledgerByAddress[msg.sender], "LIDO: NOT_FROM_LEDGER"); Types.Fee memory _fee = FEE; // it's `feeDevelopers` + `feeTreasure` uint256 _feeDevTreasure = uint256(_fee.developers + _fee.treasury); assert(_feeDevTreasure>0); fundRaisedBalance += _totalRewards; ledgerStake[msg.sender] += _totalRewards; ledgerBorrow[msg.sender] += _totalRewards; uint256 _rewards = _totalRewards * _feeDevTreasure / uint256(10000 - _fee.operators); uint256 denom = _getTotalPooledKSM() - _rewards; uint256 shares2mint = _getTotalPooledKSM(); if (denom > 0) shares2mint = _rewards * _getTotalShares() / denom; _mintShares(treasury, shares2mint); uint256 _devShares = shares2mint * uint256(_fee.developers) / _feeDevTreasure; _transferShares(treasury, developers, _devShares); _emitTransferAfterMintingShares(developers, _devShares); _emitTransferAfterMintingShares(treasury, shares2mint - _devShares); emit Rewards(msg.sender, _totalRewards, _ledgerBalance); } /** * @notice Distribute lossed by ledger, allowed to call only by ledger */ function distributeLosses(uint256 _totalLosses, uint256 _ledgerBalance) external { require(ledgerByAddress[msg.sender], "LIDO: NOT_FROM_LEDGER"); uint256 withdrawalBalance = IWithdrawal(WITHDRAWAL).totalBalanceForLosses(); uint256 withdrawalPendingForClaiming = IWithdrawal(WITHDRAWAL).pendingForClaiming(); uint256 withdrawalVKSMBalance = VKSM.balanceOf(WITHDRAWAL); // NOTE: VKSM balance that was "fasttracked" to Withdrawal can't receive slash uint256 virtualWithdrawalBalance = 0; if (withdrawalBalance + withdrawalPendingForClaiming > withdrawalVKSMBalance) { // NOTE: protection from ddos virtualWithdrawalBalance = withdrawalBalance - (withdrawalVKSMBalance - withdrawalPendingForClaiming); } // lidoPart = _totalLosses * lido_xcKSM_balance / sum_xcKSM_balance uint256 lidoPart = (_totalLosses * fundRaisedBalance) / (fundRaisedBalance + virtualWithdrawalBalance); fundRaisedBalance -= lidoPart; if ((_totalLosses - lidoPart) > 0) { IWithdrawal(WITHDRAWAL).ditributeLosses(_totalLosses - lidoPart); } // edge case when loss can be more than stake ledgerStake[msg.sender] -= ledgerStake[msg.sender] >= lidoPart ? lidoPart : ledgerStake[msg.sender]; ledgerBorrow[msg.sender] -= _totalLosses; emit Losses(msg.sender, _totalLosses, _ledgerBalance); } /** * @notice Transfer vKSM from ledger to LIDO. Can be called only from ledger * @param _amount - amount of vKSM that should be transfered * @param _excess - excess of vKSM that was transfered */ function transferFromLedger(uint256 _amount, uint256 _excess) external { require(ledgerByAddress[msg.sender], "LIDO: NOT_FROM_LEDGER"); if (_excess > 0) { // some donations fundRaisedBalance += _excess; //just distribute it as rewards bufferedDeposits += _excess; VKSM.transferFrom(msg.sender, address(this), _excess); } ledgerBorrow[msg.sender] -= _amount; VKSM.transferFrom(msg.sender, WITHDRAWAL, _amount); } /** * @notice Transfer vKSM from LIDO to ledger. Can be called only from ledger * @param _amount - amount of transfered vKSM */ function transferToLedger(uint256 _amount) external { require(ledgerByAddress[msg.sender], "LIDO: NOT_FROM_LEDGER"); require(ledgerBorrow[msg.sender] + _amount <= ledgerStake[msg.sender], "LIDO: LEDGER_NOT_ENOUGH_STAKE"); ledgerBorrow[msg.sender] += _amount; VKSM.transfer(msg.sender, _amount); } /** * @notice Flush stakes, allowed to call only by oracle master * @dev This method distributes buffered stakes between ledgers by soft manner */ function flushStakes() external { require(msg.sender == ORACLE_MASTER, "LIDO: NOT_FROM_ORACLE_MASTER"); IWithdrawal(WITHDRAWAL).newEra(); _softRebalanceStakes(); } /** * @notice Rebalance stake accross ledgers by soft manner. */ function _softRebalanceStakes() internal { uint256 totalStakeExcess = 0; for (uint256 i = 0; i < enabledLedgers.length + disabledLedgers.length; ++i) { address ledgerAddr = i < enabledLedgers.length ? enabledLedgers[i] : disabledLedgers[i - enabledLedgers.length]; // consider an incorrect case when our records about the ledger are wrong: // the ledger's active stake > the ledger's total amount of funds if (ledgerStake[ledgerAddr] > ledgerBorrow[ledgerAddr]) { uint256 ledgerStakeExcess = ledgerStake[ledgerAddr] - ledgerBorrow[ledgerAddr]; // new total stake excess <= the amount of funds that won't be sent to the ledgers if (totalStakeExcess + ledgerStakeExcess <= VKSM.balanceOf(address(this)) - bufferedDeposits) { totalStakeExcess += ledgerStakeExcess; // correcting the ledger's active stake record ledgerStake[ledgerAddr] -= ledgerStakeExcess; } } } // the amount of funds to be sent to the ledgers should decrease the ledgers' stake excess bufferedDeposits += totalStakeExcess; if (bufferedDeposits > 0 || bufferedRedeems > 0) { // first try to distribute redeems accross disabled ledgers if (disabledLedgers.length > 0 && bufferedRedeems > 0) { bufferedRedeems = _processDisabledLedgers(bufferedRedeems); } // NOTE: if we have deposits and redeems in one era we need to send all possible xcKSMs to Withdrawal if (bufferedDeposits > 0 && bufferedRedeems > 0) { uint256 maxImmediateTransfer = bufferedDeposits > bufferedRedeems ? bufferedRedeems : bufferedDeposits; bufferedDeposits -= maxImmediateTransfer; bufferedRedeems -= maxImmediateTransfer; VKSM.transfer(WITHDRAWAL, maxImmediateTransfer); } // distribute remaining stakes and redeems accross enabled if (enabledLedgers.length > 0) { int256 stake = bufferedDeposits.toInt256() - bufferedRedeems.toInt256(); if (stake != 0) { _processEnabled(stake); } bufferedDeposits = 0; bufferedRedeems = 0; } } } /** * @notice Spread redeems accross disabled ledgers * @return remainingRedeems - redeems amount which didn't distributed */ function _processDisabledLedgers(uint256 redeems) internal returns(uint256 remainingRedeems) { uint256 disabledLength = disabledLedgers.length; assert(disabledLength > 0); uint256 stakesSum = 0; uint256 actualRedeems = 0; for (uint256 i = 0; i < disabledLength; ++i) { if (!pausedledgers[disabledLedgers[i]]) { stakesSum += ledgerStake[disabledLedgers[i]]; } } if (stakesSum == 0) return redeems; for (uint256 i = 0; i < disabledLength; ++i) { if (!pausedledgers[disabledLedgers[i]]) { uint256 currentStake = ledgerStake[disabledLedgers[i]]; uint256 decrement = redeems * currentStake / stakesSum; decrement = decrement > currentStake ? currentStake : decrement; ledgerStake[disabledLedgers[i]] = currentStake - decrement; actualRedeems += decrement; } } return redeems - actualRedeems; } /** * @notice Distribute stakes and redeems accross enabled ledgers with relaxation * @dev this function should never mix bond/unbond */ function _processEnabled(int256 _stake) internal { uint256 ledgersLength = enabledLedgers.length; assert(ledgersLength > 0); int256[] memory diffs = new int256[](ledgersLength); address[] memory ledgersCache = new address[](ledgersLength); int256[] memory ledgerStakesCache = new int256[](ledgersLength); // NOTE: cache can't be used, because it can be changed or not in algorithm uint256[] memory ledgerStakePrevious = new uint256[](ledgersLength); int256 activeDiffsSum = 0; int256 totalChange = 0; int256 preciseDiffSum = 0; { uint256 targetStake = getTotalPooledKSM() / ledgersLength; int256 diff = 0; for (uint256 i = 0; i < ledgersLength; ++i) { ledgersCache[i] = enabledLedgers[i]; ledgerStakesCache[i] = int256(ledgerStake[ledgersCache[i]]); ledgerStakePrevious[i] = ledgerStake[ledgersCache[i]]; diff = int256(targetStake) - int256(ledgerStakesCache[i]); if (_stake * diff > 0) { activeDiffsSum += diff; } diffs[i] = diff; preciseDiffSum += diff; } } if (preciseDiffSum == 0 || activeDiffsSum == 0) { return; } int8 direction = 1; if (activeDiffsSum < 0) { direction = -1; activeDiffsSum = -activeDiffsSum; } for (uint256 i = 0; i < ledgersLength; ++i) { diffs[i] *= direction; if (diffs[i] > 0) { int256 change = diffs[i] * _stake / activeDiffsSum; int256 newStake = ledgerStakesCache[i] + change; ledgerStake[ledgersCache[i]] = uint256(newStake); ledgerStakesCache[i] = newStake; totalChange += change; } } { int256 remaining = _stake - totalChange; if (remaining > 0) { // just add to first ledger ledgerStake[ledgersCache[0]] += uint256(remaining); } else if (remaining < 0) { for (uint256 i = 0; i < ledgersLength && remaining < 0; ++i) { uint256 stake = uint256(ledgerStakesCache[i]); if (stake > 0) { uint256 decrement = stake > uint256(-remaining) ? uint256(-remaining) : stake; ledgerStake[ledgersCache[i]] -= decrement; remaining += int256(decrement); } } } } // NOTE: this check used to catch cases when one user redeem some funds and another deposit in next era // so ledgers stake would increase and they return less xcKSMs and remaining funds would be locked on Lido uint256 freeToTransferFunds = 0; for (uint256 i = 0; i < ledgersLength; ++i) { // NOTE: protection from double sending of funds uint256 updatedLedgerBorrow = ledgerBorrow[ledgersCache[i]] - uint256(ILedger(ledgersCache[i]).transferDownwardBalance()); if ( // NOTE: this means that we wait transfer from ledger updatedLedgerBorrow > ledgerStakePrevious[i] && // NOTE: and new deposits increase ledger stake ledgerStake[ledgersCache[i]] > ledgerStakePrevious[i] ) { freeToTransferFunds += ledgerStake[ledgersCache[i]] > updatedLedgerBorrow ? updatedLedgerBorrow - ledgerStakePrevious[i] : ledgerStake[ledgersCache[i]] - ledgerStakePrevious[i]; } } if (freeToTransferFunds > 0) { VKSM.transfer(WITHDRAWAL, uint256(freeToTransferFunds)); } } /** * @notice Set new minimum balance for ledger * @param _minNominatorBalance - new minimum nominator balance * @param _minimumBalance - new minimum active balance for ledger * @param _maxUnlockingChunks - new maximum unlocking chunks */ function _updateLedgerRelaySpecs(uint128 _minNominatorBalance, uint128 _minimumBalance, uint256 _maxUnlockingChunks) internal { for (uint i = 0; i < enabledLedgers.length + disabledLedgers.length; i++) { address ledgerAddress = i < enabledLedgers.length ? enabledLedgers[i] : disabledLedgers[i - enabledLedgers.length]; ILedger(ledgerAddress).setRelaySpecs(_minNominatorBalance, _minimumBalance, _maxUnlockingChunks); } } /** * @notice Disable ledger * @dev That method put ledger to "draining" mode, after ledger drained it can be removed * @param _ledgerAddress - target ledger address */ function _disableLedger(address _ledgerAddress) internal { require(ledgerByAddress[_ledgerAddress], "LIDO: LEDGER_NOT_FOUND"); uint256 ledgerIdx = _findLedger(_ledgerAddress, true); require(ledgerIdx != type(uint256).max, "LIDO: LEDGER_NOT_ENABLED"); address lastLedger = enabledLedgers[enabledLedgers.length - 1]; enabledLedgers[ledgerIdx] = lastLedger; enabledLedgers.pop(); disabledLedgers.push(_ledgerAddress); emit LedgerDisable(_ledgerAddress); } /** * @notice Emits an {Transfer} event where from is 0 address. Indicates mint events. */ function _emitTransferAfterMintingShares(address _to, uint256 _sharesAmount) internal { emit Transfer(address(0), _to, getPooledKSMByShares(_sharesAmount)); } /** * @notice Returns amount of total pooled tokens by contract. * @return amount of pooled vKSM in contract */ function _getTotalPooledKSM() internal view override returns (uint256) { return fundRaisedBalance; } /** * @notice Returns enabled or disabled ledger index by given address * @return enabled or disabled ledger index or uint256_max if not found */ function _findLedger(address _ledgerAddress, bool _enabled) internal view returns(uint256) { uint256 length = _enabled ? enabledLedgers.length : disabledLedgers.length; for (uint256 i = 0; i < length; ++i) { address ledgerAddress = _enabled ? enabledLedgers[i] : disabledLedgers[i]; if (ledgerAddress == _ledgerAddress) { return i; } } return type(uint256).max; } }
// 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; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { require(value < 2**255, "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// 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; interface IOracleMaster { function addLedger(address ledger) external; function removeLedger(address ledger) external; function getOracle(address ledger) view external returns (address); function eraId() view external returns (uint64); function setLido(address lido) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ILedgerFactory { function createLedger( bytes32 _stashAccount, bytes32 _controllerAccount, address _vKSM, address _controller, uint128 _minNominatorBalance, uint128 _minimumBalance, uint256 _maxUnlockingChunks ) external returns (address); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "Types.sol"; interface ILedger { function initialize( bytes32 _stashAccount, bytes32 controllerAccount, address vKSM, address controller, uint128 minNominatorBalance, address lido, uint128 _minimumBalance, uint256 _maxUnlockingChunks ) external; function pushData(uint64 eraId, Types.OracleData calldata staking) external; function nominate(bytes32[] calldata validators) external; function status() external view returns (Types.LedgerStatus); function isEmpty() external view returns (bool); function stashAccount() external view returns (bytes32); function totalBalance() external view returns (uint128); function setRelaySpecs(uint128 minNominatorBalance, uint128 minimumBalance, uint256 _maxUnlockingChunks) external; function cachedTotalBalance() external view returns (uint128); function transferDownwardBalance() external view returns (uint128); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface Types { struct Fee{ uint16 total; uint16 operators; uint16 developers; uint16 treasury; } struct Stash { bytes32 stashAccount; uint64 eraId; } enum LedgerStatus { // bonded but not participate in staking Idle, // participate as nominator Nominator, // participate as validator Validator, // not bonded not participate in staking None } struct UnlockingChunk { uint128 balance; uint64 era; } struct OracleData { bytes32 stashAccount; bytes32 controllerAccount; LedgerStatus stakeStatus; // active part of stash balance uint128 activeBalance; // locked for stake stash balance. uint128 totalBalance; // totalBalance = activeBalance + sum(unlocked.balance) UnlockingChunk[] unlocking; uint32[] claimedRewards; // stash account balance. It includes locked (totalBalance) balance assigned // to a controller. uint128 stashBalance; // slashing spans for ledger uint32 slashingSpans; } struct RelaySpec { uint16 maxValidatorsPerLedger; uint128 minNominatorBalance; uint128 ledgerMinimumActiveBalance; uint256 maxUnlockingChunks; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IController { function newSubAccount(uint16 index, bytes32 accountId, address paraAddress) external; function deleteSubAccount(address paraAddress) external; function nominate(bytes32[] calldata _validators) external; function bond(bytes32 controller, uint256 amount) external; function bondExtra(uint256 amount) external; function unbond(uint256 amount) external; function withdrawUnbonded(uint32 slashingSpans) external; function rebond(uint256 amount, uint256 unbondingChunks) external; function chill() external; function transferToParachain(uint256 amount) external; function transferToRelaychain(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IAuthManager { function has(bytes32 role, address member) external view returns (bool); function add(bytes32 role, address member) external; function remove(bytes32 role, address member) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IWithdrawal { // total virtual xcKSM amount on contract function totalVirtualXcKSMAmount() external returns (uint256); // Set stKSM contract address, allowed to only once function setStKSM(address _stKSM) external; // Returns total virtual xcKSM balance of contract for which losses can be applied function totalBalanceForLosses() external view returns (uint256); // Returns total xcKSM balance of contract which waiting for claim function pendingForClaiming() external view returns (uint256); // Burn pool shares from first element of queue and move index for allow claiming. After that add new batch function newEra() external; // Mint equal amount of pool shares for user. Adjust current amount of virtual xcKSM on Withdrawal contract. // Burn shares on LIDO side function redeem(address _from, uint256 _amount) external; // Returns available for claiming xcKSM amount for user function claim(address _holder) external returns (uint256); // Apply losses to current stKSM shares on this contract function ditributeLosses(uint256 _losses) external; // Check available for claim xcKSM balance for user function getRedeemStatus(address _holder) external view returns(uint256 _waiting, uint256 _available); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "IERC20.sol"; import "Pausable.sol"; abstract contract stKSM is IERC20, Pausable { /** * @dev stKSM balances are dynamic and are calculated based on the accounts' shares * and the total amount of KSM controlled by the protocol. Account shares aren't * normalized, so the contract also stores the sum of all shares to calculate * each account's token balance which equals to: * * shares[account] * _getTotalPooledKSM() / _getTotalShares() */ mapping (address => uint256) private shares; /** * @dev Allowances are nominated in tokens, not token shares. */ mapping (address => mapping (address => uint256)) private allowances; /** * @dev Storage position used for holding the total amount of shares in existence. */ uint256 internal totalShares; /** * @return the amount of tokens in existence. * * @dev Always equals to `_getTotalPooledKSM()` since token amount * is pegged to the total amount of KSM controlled by the protocol. */ function totalSupply() public view override returns (uint256) { return _getTotalPooledKSM(); } /** * @return the entire amount of KSMs controlled by the protocol. * * @dev The sum of all KSM balances in the protocol. */ function getTotalPooledKSM() public view returns (uint256) { return _getTotalPooledKSM(); } /** * @return the amount of tokens owned by the `_account`. * * @dev Balances are dynamic and equal the `_account`'s share in the amount of the * total KSM controlled by the protocol. See `sharesOf`. */ function balanceOf(address _account) public view override returns (uint256) { return getPooledKSMByShares(_sharesOf(_account)); } /** * @notice Moves `_amount` tokens from the caller's account to the `_recipient` account. * * @return a boolean value indicating whether the operation succeeded. * Emits a `Transfer` event. * * Requirements: * * - `_recipient` cannot be the zero address. * - the caller must have a balance of at least `_amount`. * - the contract must not be paused. * * @dev The `_amount` argument is the amount of tokens, not shares. */ function transfer(address _recipient, uint256 _amount) public override returns (bool) { _transfer(msg.sender, _recipient, _amount); return true; } /** * @return the remaining number of tokens that `_spender` is allowed to spend * on behalf of `_owner` through `transferFrom`. This is zero by default. * * @dev This value changes when `approve` or `transferFrom` is called. */ function allowance(address _owner, address _spender) public view override returns (uint256) { return allowances[_owner][_spender]; } /** * @notice Sets `_amount` as the allowance of `_spender` over the caller's tokens. * * @return a boolean value indicating whether the operation succeeded. * Emits an `Approval` event. * * Requirements: * * - `_spender` cannot be the zero address. * - the contract must not be paused. * * @dev The `_amount` argument is the amount of tokens, not shares. */ function approve(address _spender, uint256 _amount) public override returns (bool) { _approve(msg.sender, _spender, _amount); return true; } /** * @notice Moves `_amount` tokens from `_sender` to `_recipient` using the * allowance mechanism. `_amount` is then deducted from the caller's * allowance. * * @return a boolean value indicating whether the operation succeeded. * * Emits a `Transfer` event. * Emits an `Approval` event indicating the updated allowance. * * Requirements: * * - `_sender` and `_recipient` cannot be the zero addresses. * - `_sender` must have a balance of at least `_amount`. * - the caller must have allowance for `_sender`'s tokens of at least `_amount`. * - the contract must not be paused. * * @dev The `_amount` argument is the amount of tokens, not shares. */ function transferFrom(address _sender, address _recipient, uint256 _amount) public override returns (bool) { uint256 currentAllowance = allowances[_sender][msg.sender]; require(currentAllowance >= _amount, "TRANSFER_AMOUNT_EXCEEDS_ALLOWANCE"); _transfer(_sender, _recipient, _amount); _approve(_sender, msg.sender, currentAllowance -_amount); return true; } /** * @notice Atomically increases the allowance granted to `_spender` by the caller by `_addedValue`. * * This is an alternative to `approve` that can be used as a mitigation for * problems described in: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42 * Emits an `Approval` event indicating the updated allowance. * * Requirements: * * - `_spender` cannot be the the zero address. * - the contract must not be paused. */ function increaseAllowance(address _spender, uint256 _addedValue) public returns (bool) { _approve(msg.sender, _spender, allowances[msg.sender][_spender] + _addedValue); return true; } /** * @notice Atomically decreases the allowance granted to `_spender` by the caller by `_subtractedValue`. * * This is an alternative to `approve` that can be used as a mitigation for * problems described in: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42 * Emits an `Approval` event indicating the updated allowance. * * Requirements: * * - `_spender` cannot be the zero address. * - `_spender` must have allowance for the caller of at least `_subtractedValue`. * - the contract must not be paused. */ function decreaseAllowance(address _spender, uint256 _subtractedValue) public returns (bool) { uint256 currentAllowance = allowances[msg.sender][_spender]; require(currentAllowance >= _subtractedValue, "DECREASED_ALLOWANCE_BELOW_ZERO"); _approve(msg.sender, _spender, currentAllowance-_subtractedValue); return true; } /** * @return the total amount of shares in existence. * * @dev The sum of all accounts' shares can be an arbitrary number, therefore * it is necessary to store it in order to calculate each account's relative share. */ function getTotalShares() public view returns (uint256) { return _getTotalShares(); } /** * @return the amount of shares owned by `_account`. */ function sharesOf(address _account) public view returns (uint256) { return _sharesOf(_account); } /** * @return the amount of shares that corresponds to `_ethAmount` protocol-controlled KSM. */ function getSharesByPooledKSM(uint256 _amount) public view returns (uint256) { uint256 totalPooledKSM = _getTotalPooledKSM(); if (totalPooledKSM == 0) { return 0; } else { return _amount * _getTotalShares() / totalPooledKSM; } } /** * @return the amount of KSM that corresponds to `_sharesAmount` token shares. */ function getPooledKSMByShares(uint256 _sharesAmount) public view returns (uint256) { uint256 _totalShares = _getTotalShares(); if (totalShares == 0) { return 0; } else { return _sharesAmount * _getTotalPooledKSM() / _totalShares; } } /** * @return the total amount (in wei) of KSM controlled by the protocol. * @dev This is used for calaulating tokens from shares and vice versa. * @dev This function is required to be implemented in a derived contract. */ function _getTotalPooledKSM() internal view virtual returns (uint256); /** * @notice Moves `_amount` tokens from `_sender` to `_recipient`. * Emits a `Transfer` event. */ function _transfer(address _sender, address _recipient, uint256 _amount) internal { uint256 _sharesToTransfer = getSharesByPooledKSM(_amount); _transferShares(_sender, _recipient, _sharesToTransfer); emit Transfer(_sender, _recipient, _amount); } /** * @notice Sets `_amount` as the allowance of `_spender` over the `_owner` s tokens. * * Emits an `Approval` event. * * Requirements: * * - `_owner` cannot be the zero address. * - `_spender` cannot be the zero address. * - the contract must not be paused. */ function _approve(address _owner, address _spender, uint256 _amount) internal whenNotPaused { require(_owner != address(0), "APPROVE_FROM_ZERO_ADDRESS"); require(_spender != address(0), "APPROVE_TO_ZERO_ADDRESS"); allowances[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); } /** * @return the total amount of shares in existence. */ function _getTotalShares() internal view returns (uint256) { return totalShares; } /** * @return the amount of shares owned by `_account`. */ function _sharesOf(address _account) internal view returns (uint256) { return shares[_account]; } /** * @notice Moves `_sharesAmount` shares from `_sender` to `_recipient`. * * Requirements: * * - `_sender` cannot be the zero address. * - `_recipient` cannot be the zero address. * - `_sender` must hold at least `_sharesAmount` shares. * - the contract must not be paused. */ function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal whenNotPaused { require(_sender != address(0), "TRANSFER_FROM_THE_ZERO_ADDRESS"); require(_recipient != address(0), "TRANSFER_TO_THE_ZERO_ADDRESS"); uint256 currentSenderShares = shares[_sender]; require(_sharesAmount <= currentSenderShares, "TRANSFER_AMOUNT_EXCEEDS_BALANCE"); shares[_sender] = currentSenderShares - _sharesAmount; shares[_recipient] = shares[_recipient] + _sharesAmount; } /** * @notice Creates `_sharesAmount` shares and assigns them to `_recipient`, increasing the total amount of shares. * @dev This doesn't increase the token total supply. * * Requirements: * * - `_recipient` cannot be the zero address. * - the contract must not be paused. */ function _mintShares(address _recipient, uint256 _sharesAmount) internal whenNotPaused returns (uint256 newTotalShares) { require(_recipient != address(0), "MINT_TO_THE_ZERO_ADDRESS"); newTotalShares = _getTotalShares() + _sharesAmount; totalShares = newTotalShares; shares[_recipient] = shares[_recipient] + _sharesAmount; // Notice: we're not emitting a Transfer event from the zero address here since shares mint // works by taking the amount of tokens corresponding to the minted shares from all other // token holders, proportionally to their share. The total supply of the token doesn't change // as the result. This is equivalent to performing a send from each other token holder's // address to `address`, but we cannot reflect this as it would require sending an unbounded // number of events. } /** * @notice Destroys `_sharesAmount` shares from `_account`'s holdings, decreasing the total amount of shares. * @dev This doesn't decrease the token total supply. * * Requirements: * * - `_account` cannot be the zero address. * - `_account` must hold at least `_sharesAmount` shares. * - the contract must not be paused. */ function _burnShares(address _account, uint256 _sharesAmount) internal whenNotPaused returns (uint256 newTotalShares) { require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS"); uint256 accountShares = shares[_account]; require(_sharesAmount <= accountShares, "BURN_AMOUNT_EXCEEDS_BALANCE"); newTotalShares = _getTotalShares() - _sharesAmount; totalShares = newTotalShares; shares[_account] = accountShares - _sharesAmount; // Notice: we're not emitting a Transfer event to the zero address here since shares burn // works by redistributing the amount of tokens corresponding to the burned shares between // all other token holders. The total supply of the token doesn't change as the result. // This is equivalent to performing a send from `address` to each other token holder address, // but we cannot reflect this as it would require sending an unbounded number of events. } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// 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; } }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 5 }, "libraries": { "Lido.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"fee","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"feeOperatorsBP","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"feeTreasuryBP","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"feeDevelopersBP","type":"uint16"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bytes32","name":"stashAccount","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"controllerAccount","type":"bytes32"}],"name":"LedgerAdd","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"LedgerDisable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"LedgerPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"LedgerRemove","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"LedgerResumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"ledger","type":"address"},{"indexed":false,"internalType":"uint256","name":"losses","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Losses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Redeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddr","type":"address"},{"indexed":false,"internalType":"address","name":"referralAddr","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Referral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"ledger","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"}],"name":"Rewards","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":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"AUTH_MANAGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEDGER_BEACON","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ALLOWABLE_DIFFERENCE","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_MASTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_stashAccount","type":"bytes32"},{"internalType":"bytes32","name":"_controllerAccount","type":"bytes32"},{"internalType":"uint16","name":"_index","type":"uint16"}],"name":"addLedger","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bufferedDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bufferedRedeems","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimUnbonded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_referral","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ledgerAddress","type":"address"}],"name":"disableLedger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalLosses","type":"uint256"},{"internalType":"uint256","name":"_ledgerBalance","type":"uint256"}],"name":"distributeLosses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_totalRewards","type":"uint256"},{"internalType":"uint256","name":"_ledgerBalance","type":"uint256"}],"name":"distributeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ledgerAddress","type":"address"}],"name":"emergencyPauseLedger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_stashAccount","type":"bytes32"}],"name":"findLedger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flushStakes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundRaisedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLedgerAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sharesAmount","type":"uint256"}],"name":"getPooledKSMByShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getSharesByPooledKSM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStashAccounts","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalPooledKSM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_holder","type":"address"}],"name":"getUnbonded","outputs":[{"internalType":"uint256","name":"waiting","type":"uint256"},{"internalType":"uint256","name":"unbonded","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_authManager","type":"address"},{"internalType":"address","name":"_vKSM","type":"address"},{"internalType":"address","name":"_controller","type":"address"},{"internalType":"address","name":"_developers","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_oracleMaster","type":"address"},{"internalType":"address","name":"_withdrawal","type":"address"},{"internalType":"uint256","name":"_depositCap","type":"uint256"},{"internalType":"uint128","name":"_maxAllowableDifference","type":"uint128"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ledgerBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ledgerStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_stashAccounts","type":"bytes32[]"},{"internalType":"bytes32[][]","name":"_validators","type":"bytes32[][]"}],"name":"nominateBatch","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":"uint256","name":"_amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ledgerAddress","type":"address"}],"name":"removeLedger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resume","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ledgerAddress","type":"address"}],"name":"resumeLedger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositCap","type":"uint256"}],"name":"setDepositCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_developers","type":"address"}],"name":"setDevelopers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeOperators","type":"uint16"},{"internalType":"uint16","name":"_feeTreasury","type":"uint16"},{"internalType":"uint16","name":"_feeDevelopers","type":"uint16"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ledgerBeacon","type":"address"}],"name":"setLedgerBeacon","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ledgerFactory","type":"address"}],"name":"setLedgerFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_maxAllowableDifference","type":"uint128"}],"name":"setMaxAllowableDifference","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"maxValidatorsPerLedger","type":"uint16"},{"internalType":"uint128","name":"minNominatorBalance","type":"uint128"},{"internalType":"uint128","name":"ledgerMinimumActiveBalance","type":"uint128"},{"internalType":"uint256","name":"maxUnlockingChunks","type":"uint256"}],"internalType":"struct Types.RelaySpec","name":"_relaySpec","type":"tuple"}],"name":"setRelaySpec","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_treasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"sharesOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_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":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_excess","type":"uint256"}],"name":"transferFromLedger","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToLedger","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506000805460ff19169055615d9e806200002b6000396000f3fe608060405234801561001057600080fd5b50600436106102935760003560e01c8063046f7da21461029857806306fdde03146102a2578063095ea7b3146102c057806318160ddd146102e35780631a813a3c146102f95780631ab81cba146103015780631d55fde41461031457806323b872dd14610329578063240359bc1461033c578063313ce5671461037257806338dee1d314610387578063395093511461039a5780633ca3bca3146103ad5780633fd2c16a146103c057806341c262c5146103d357806347376473146103e657806348c696c0146103f95780634fe28e3a146104025780635c975abb146104155780635e442a9b146104205780635f3f2cac1461044057806361f9c3da1461045357806363ca402d146104665780636a92b586146104795780636e553f65146104a457806370a08231146104b757806373ece435146104ca57806377c96574146104dd5780638456cb5914610505578063866512031461050d5780638ab476bf1461052057806395d89b41146105335780639e0c97041461053b578063a1e206c71461054e578063a457c2d714610561578063a9042441146102e3578063a9059cbb14610574578063b09f532014610587578063b31207f214610590578063b6b55f25146105a3578063cdd8f598146105b6578063d381787a146105c9578063d5002f2e146105dc578063db006a75146105e4578063dbd5edc7146105f7578063dd62ed3e14610600578063df19795614610639578063df6c39fb1461064e578063e100610714610661578063e40b925514610674578063ec70d8001461067d578063f0f4426014610690578063f1447195146106a3578063f339a70d146106c3578063f5eb42dc146106d6578063f7eba420146106e9578063fa597e07146106fc575b600080fd5b6102a0610704565b005b6102aa6107b5565b6040516102b791906152cb565b60405180910390f35b6102d36102ce366004615335565b610847565b60405190151581526020016102b7565b6102eb61085e565b6040519081526020016102b7565b6102a061086e565b6102a061030f366004615361565b610940565b61031c610a9b565b6040516102b7919061537e565b6102d36103373660046153c2565b610c17565b61036561034a366004615403565b6000908152601b60205260409020546001600160a01b031690565b6040516102b7919061541c565b60215460405160ff90911681526020016102b7565b6102a0610395366004615430565b610cbf565b6102d36103a8366004615335565b610e6f565b6102a06103bb366004615457565b610ea6565b601154610365906001600160a01b031681565b6102a06103e1366004615555565b61134f565b6102a06103f4366004615361565b61161b565b6102eb60075481565b6103656104103660046155d0565b611731565b60005460ff166102d3565b6102eb61042e366004615361565b60096020526000908152604090205481565b6102a061044e366004615609565b611bd9565b6102a0610461366004615626565b611d03565b6102eb610474366004615403565b611e86565b601a5461048c906001600160801b031681565b6040516001600160801b0390911681526020016102b7565b6102eb6104b2366004615648565b611ecd565b6102eb6104c5366004615361565b611f33565b6102a06104d8366004615678565b611f41565b6104f06104eb366004615361565b61214b565b604080519283526020830191909152016102b7565b6102a06121c9565b6102a061051b366004615403565b61226e565b6102a061052e366004615361565b61235b565b6102aa61248e565b6102a0610549366004615626565b61249d565b600f54610365906001600160a01b031681565b6102d361056f366004615335565b6127d6565b6102d3610582366004615335565b612863565b6102eb60065481565b6102eb61059e366004615403565b612870565b6102eb6105b1366004615403565b612896565b6102a06105c4366004615361565b6128a1565b6102a06105d7366004615361565b61299a565b6102eb612e79565b6102a06105f2366004615403565b612e84565b6102eb600c5481565b6102eb61060e3660046156b8565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61064161305d565b6040516102b791906156e6565b6102a061065c366004615626565b613178565b6102a061066f366004615403565b6133b7565b6102eb60055481565b601754610365906001600160a01b031681565b6102a061069e366004615361565b6134f4565b6102eb6106b1366004615361565b60086020526000908152604090205481565b6102a06106d1366004615361565b61361c565b6102eb6106e4366004615361565b6136c2565b6102a06106f7366004615361565b6136cd565b6102a06137e3565b600f54604051633bfc46cb60e21b8152600080516020615d29833981519152916001600160a01b03169063eff11b2c906107449084903390600401615727565b602060405180830381865afa158015610761573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610785919061573e565b6107aa5760405162461bcd60e51b81526004016107a190615760565b60405180910390fd5b6107b26138ae565b50565b6060601f80546107c49061578c565b80601f01602080910402602001604051908101604052809291908181526020018280546107f09061578c565b801561083d5780601f106108125761010080835404028352916020019161083d565b820191906000526020600020905b81548152906001019060200180831161082057829003601f168201915b5050505050905090565b600061085433848461393b565b5060015b92915050565b600061086960055490565b905090565b60005460ff16156108915760405162461bcd60e51b81526004016107a1906157c1565b601954604051630f41a04d60e11b81526000916001600160a01b031690631e83409a906108c290339060040161541c565b6020604051808303816000875af11580156108e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090591906157eb565b60405181815290915033907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a250565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c906109809084903390600401615727565b602060405180830381865afa15801561099d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c1919061573e565b6109dd5760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166000908152601d602052604090205460ff16610a3f5760405162461bcd60e51b815260206004820152601760248201527613125113ce8813115111d15497d393d517d4105554d151604a1b60448201526064016107a1565b6001600160a01b0382166000908152601d602052604090819020805460ff19169055517f8c097d4c8d964b147a04f3a822a31e3aa5a9104dc7db3dde0166a248b8f106c590610a8f90849061541c565b60405180910390a15050565b600a54600b54606091600091610ab1919061581a565b6001600160401b03811115610ac857610ac8615832565b604051908082528060200260200182016040528015610af1578160200160208202803683370190505b50905060005b600a54600b54610b07919061581a565b811015610c1157600b546000908210610b5457600b54600a90610b2a9084615848565b81548110610b3a57610b3a61585f565b6000918252602090912001546001600160a01b0316610b7d565b600b8281548110610b6757610b6761585f565b6000918252602090912001546001600160a01b03165b9050806001600160a01b031663231aebf26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be191906157eb565b838381518110610bf357610bf361585f565b60209081029190910101525080610c0981615875565b915050610af7565b50919050565b6001600160a01b038316600090815260026020908152604080832033845290915281205482811015610c955760405162461bcd60e51b815260206004820152602160248201527f5452414e534645525f414d4f554e545f455843454544535f414c4c4f57414e436044820152604560f81b60648201526084016107a1565b610ca0858585613a61565b610cb48533610caf8685615848565b61393b565b506001949350505050565b600f54604051633bfc46cb60e21b81527f2c204f3ef59cc164f843cf6919920470e37721ba425db7893d02e60cfd0bafdc916001600160a01b03169063eff11b2c90610d119084903390600401615727565b602060405180830381865afa158015610d2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d52919061573e565b610d6e5760405162461bcd60e51b81526004016107a190615760565b6000610d7d6020840184615890565b61ffff1611610dda5760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a204241445f4d41585f56414c494441544f52535f5045525f4c454460448201526223a2a960e91b60648201526084016107a1565b6000826060013511610e2e5760405162461bcd60e51b815260206004820152601e60248201527f4c49444f3a204241445f4d41585f554e4c4f434b494e475f4348554e4b53000060448201526064016107a1565b816012610e3b82826158ad565b50610e6b9050610e516040840160208501615609565b610e616060850160408601615609565b8460600135613aba565b5050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610854918590610caf90869061581a565b600454610100900460ff1680610ebf575060045460ff16155b610f225760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016107a1565b600454610100900460ff16158015610f44576004805461ffff19166101011790555b60008311610f855760405162461bcd60e51b815260206004820152600e60248201526d04c49444f3a205a45524f5f4341560941b60448201526064016107a1565b6001600160a01b038916610fda5760405162461bcd60e51b815260206004820152601c60248201527b4c49444f3a20494e434f52524543545f564b534d5f4144445245535360201b60448201526064016107a1565b6001600160a01b03851661103e5760405162461bcd60e51b815260206004820152602560248201527f4c49444f3a20494e434f52524543545f4f5241434c455f4d41535445525f4144604482015264445245535360d81b60648201526084016107a1565b6001600160a01b03841661109f5760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f5749544844524157414c5f4144445245604482015261535360f01b60648201526084016107a1565b6001600160a01b038a166111015760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a20494e434f52524543545f415554484d414e414745525f4144445260448201526245535360e81b60648201526084016107a1565b6001600160a01b0388166111625760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f434f4e54524f4c4c45525f4144445245604482015261535360f01b60648201526084016107a1565b600d80546001600160a01b03808c166001600160a01b031992831617909255600e80548b8416908316179055600f8054928d1692909116919091179055600c83905560c86010556111b16152a4565b6103206111c060c8600061593a565b6111ca919061593a565b61ffff168082526000602083015260c86040808401919091526103206060840152601e805465ffffffffffff1916909217601960231b1761ffff60301b1916601960351b17909155601680546001600160a01b03199081166001600160a01b038b8116919091179092556015805482168c84161790556011805490911691891691821790559051637d774e3160e01b8152637d774e319061126f90309060040161541c565b600060405180830381600087803b15801561128957600080fd5b505af115801561129d573d6000803e3d6000fd5b5050601980546001600160a01b0319166001600160a01b03891690811790915560405163015cda1760e41b81529092506315cda17091506112e290309060040161541c565b600060405180830381600087803b1580156112fc57600080fd5b505af1158015611310573d6000803e3d6000fd5b5050601a80546001600160801b0319166001600160801b038716179055505081159050611343576004805461ff00191690555b50505050505050505050565b600f54604051633bfc46cb60e21b81527fdefdc47e8c8311059971baa7eda778fd22d6ea93a75a917e77534b8ce74fe4f9916001600160a01b03169063eff11b2c906113a19084903390600401615727565b602060405180830381865afa1580156113be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e2919061573e565b6113fe5760405162461bcd60e51b81526004016107a190615760565b8382146114455760405162461bcd60e51b815260206004820152601560248201527413125113ce88125390d3d4949150d517d253941555605a1b60448201526064016107a1565b60005b84811015611613576000601b818888858181106114675761146761585f565b60209081029290920135835250810191909152604001600020546001600160a01b031614156114d65760405162461bcd60e51b815260206004820152601b60248201527a13125113ce88155392d393d5d397d4d51054d217d050d0d3d55395602a1b60448201526064016107a1565b60125461ffff168484838181106114ef576114ef61585f565b90506020028101906115019190615960565b905011156115515760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a2056414c494441544f52535f414d4f554e545f544f4f5f4249470060448201526064016107a1565b601b60008787848181106115675761156761585f565b60209081029290920135835250810191909152604001600020546001600160a01b031663f5330e968585848181106115a1576115a161585f565b90506020028101906115b39190615960565b6040518363ffffffff1660e01b81526004016115d09291906159a9565b600060405180830381600087803b1580156115ea57600080fd5b505af11580156115fe573d6000803e3d6000fd5b505050508061160c90615875565b9050611448565b505050505050565b600f54604051633bfc46cb60e21b8152600080516020615d09833981519152916001600160a01b03169063eff11b2c9061165b9084903390600401615727565b602060405180830381865afa158015611678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169c919061573e565b6116b85760405162461bcd60e51b81526004016107a190615760565b6001600160a01b03821661170e5760405162461bcd60e51b815260206004820152601e60248201527f4c49444f3a20494e434f52524543545f424541434f4e5f41444452455353000060448201526064016107a1565b50601780546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604051633bfc46cb60e21b8152600091600080516020615ce9833981519152916001600160a01b039091169063eff11b2c906117769084903390600401615727565b602060405180830381865afa158015611793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b7919061573e565b6117d35760405162461bcd60e51b81526004016107a190615760565b6017546001600160a01b031661182b5760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a20554e5350454349464945445f4c45444745525f424541434f4e0060448201526064016107a1565b6018546001600160a01b03166118835760405162461bcd60e51b815260206004820181905260248201527f4c49444f3a20554e5350454349464945445f4c45444745525f464143544f525960448201526064016107a1565b6011546001600160a01b03166118d45760405162461bcd60e51b81526020600482015260166024820152752624a2279d102727afa7a920a1a622afa6a0a9aa22a960511b60448201526064016107a1565b601054600a54600b546118e7919061581a565b1061192f5760405162461bcd60e51b815260206004820152601860248201527713125113ce8813115111d15494d7d413d3d317d31253525560421b60448201526064016107a1565b6000858152601b60205260409020546001600160a01b0316156119915760405162461bcd60e51b815260206004820152601a6024820152794c49444f3a2053544153485f414c52454144595f45584953545360301b60448201526064016107a1565b601854600d54600e5460125460135460145460405163776aecef60e11b8152600481018c9052602481018b90526001600160a01b0395861660448201529385166064850152620100009092046001600160801b0390811660848501521660a483015260c4820152600092919091169063eed5d9de9060e4016020604051808303816000875af1158015611a28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4c91906159e5565b600b805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b038085166001600160a01b0319928316811790935560008b8152601b6020908152604080832080549095168617909455938152601c90935291819020805460ff191690931790925560115491516327c13a6b60e21b81529293501690639f04e9ac90611af390849060040161541c565b600060405180830381600087803b158015611b0d57600080fd5b505af1158015611b21573d6000803e3d6000fd5b5050600e54604051639632acf760e01b815261ffff88166004820152602481018a90526001600160a01b0385811660448301529091169250639632acf79150606401600060405180830381600087803b158015611b7d57600080fd5b505af1158015611b91573d6000803e3d6000fd5b505050507f4522989a180263bb7fbc1471718de7bdd69a5d36b5d29511958afa11d2e9da04818787604051611bc893929190615a02565b60405180910390a195945050505050565b600f54604051633bfc46cb60e21b8152600080516020615d09833981519152916001600160a01b03169063eff11b2c90611c199084903390600401615727565b602060405180830381865afa158015611c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5a919061573e565b611c765760405162461bcd60e51b81526004016107a190615760565b6000826001600160801b031611611ce05760405162461bcd60e51b815260206004820152602860248201527f4c49444f3a20494e434f52524543545f4d41585f414c4c4f5741424c455f444960448201526746464552454e434560c01b60648201526084016107a1565b50601a80546001600160801b0319166001600160801b0392909216919091179055565b336000908152601c602052604090205460ff16611d325760405162461bcd60e51b81526004016107a190615a23565b8015611de1578060056000828254611d4a919061581a565b925050819055508060066000828254611d63919061581a565b9091555050600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611d9c90339030908690600401615a52565b6020604051808303816000875af1158015611dbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddf919061573e565b505b3360009081526009602052604081208054849290611e00908490615848565b9091555050600d546019546040516323b872dd60e01b81526001600160a01b03928316926323b872dd92611e3e923392909116908790600401615a52565b6020604051808303816000875af1158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e81919061573e565b505050565b600080611e9260035490565b905060035460001415611ea85750600092915050565b80611eb260055490565b611ebc9085615a76565b611ec69190615aab565b9392505050565b600080611ed984613bd1565b604080513381526001600160a01b0386166020820152908101869052606081018290529091507f90f46099733ed637df811df4fcc5cae4961192ca04f36da9ab64b4dd8dc9b7f59060800160405180910390a19392505050565b600061085861047483613d9f565b600f54604051633bfc46cb60e21b81527f0fc26914248bb9568b0afb008dd993637f6fb6bdc9598c222c68a21e90ca53c1916001600160a01b03169063eff11b2c90611f939084903390600401615727565b602060405180830381865afa158015611fb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd4919061573e565b611ff05760405162461bcd60e51b81526004016107a190615760565b611ff86152a4565b82612003868661593a565b61200d919061593a565b61ffff1680825261271010801590612037575060008461ffff161180612037575060008361ffff16115b801561204857506127108561ffff16105b61208c5760405162461bcd60e51b815260206004820152601560248201527404c49444f3a204645455f444f4e545f4144445f555605c1b60448201526064016107a1565b80516040805161ffff92831681528783166020820152868316818301529185166060830152517fb01998f6d1382c5b6c7a4b477769ce2ffbbb91adc291994665b24def9a47e4509181900360800190a161ffff9283166040820181905294831660208201819052938316606082018190529051601e80549190941663ffffffff1990911617620100009094029390931763ffffffff60201b1916600160201b90940261ffff60301b191693909317600160301b90920291909117905550565b601954604051630aff799160e41b815260009182916001600160a01b039091169063aff799109061218090869060040161541c565b6040805180830381865afa15801561219c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c09190615abf565b91509150915091565b600f54604051633bfc46cb60e21b8152600080516020615d29833981519152916001600160a01b03169063eff11b2c906122099084903390600401615727565b602060405180830381865afa158015612226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224a919061573e565b6122665760405162461bcd60e51b81526004016107a190615760565b6107b2613dba565b600f54604051633bfc46cb60e21b8152600080516020615d29833981519152916001600160a01b03169063eff11b2c906122ae9084903390600401615727565b602060405180830381865afa1580156122cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ef919061573e565b61230b5760405162461bcd60e51b81526004016107a190615760565b600082116123555760405162461bcd60e51b815260206004820152601760248201527604c49444f3a20494e434f52524543545f4e45575f43415604c1b60448201526064016107a1565b50600c55565b600f54604051633bfc46cb60e21b81527fbd1ecc6a842ff1f2601eedd75a87543c45753bbba85c665c9f8870558fb3a2cf916001600160a01b03169063eff11b2c906123ad9084903390600401615727565b602060405180830381865afa1580156123ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ee919061573e565b61240a5760405162461bcd60e51b81526004016107a190615760565b6001600160a01b03821661246b5760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f444556454c4f504552535f4144445245604482015261535360f01b60648201526084016107a1565b50601580546001600160a01b0319166001600160a01b0392909216919091179055565b6060602080546107c49061578c565b336000908152601c602052604090205460ff166124cc5760405162461bcd60e51b81526004016107a190615a23565b601954604080516301b7603360e11b815290516000926001600160a01b03169163036ec0669160048083019260209291908290030181865afa158015612516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253a91906157eb565b90506000601960009054906101000a90046001600160a01b03166001600160a01b0316633dbfe6cb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612591573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b591906157eb565b600d546019546040516370a0823160e01b81529293506000926001600160a01b03928316926370a08231926125ef9291169060040161541c565b602060405180830381865afa15801561260c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263091906157eb565b905060008161263f848661581a565b111561265c5761264f8383615848565b6126599085615848565b90505b60008160055461266c919061581a565b6005546126799089615a76565b6126839190615aab565b905080600560008282546126979190615848565b90915550600090506126a98289615848565b111561271b576019546001600160a01b0316634f5b636c6126ca838a615848565b6040518263ffffffff1660e01b81526004016126e891815260200190565b600060405180830381600087803b15801561270257600080fd5b505af1158015612716573d6000803e3d6000fd5b505050505b336000908152600860205260409020548111156127475733600090815260086020526040902054612749565b805b3360009081526008602052604081208054909190612768908490615848565b9091555050336000908152600960205260408120805489929061278c908490615848565b90915550506040517f28457ba4ae46aeb68ba5c1a1c15506fb3212bfff27da04dee70b81023a9ebc04906127c59033908a908a90615a02565b60405180910390a150505050505050565b3360009081526002602090815260408083206001600160a01b03861684529091528120548281101561284a5760405162461bcd60e51b815260206004820152601e60248201527f4445435245415345445f414c4c4f57414e43455f42454c4f575f5a45524f000060448201526064016107a1565b6128593385610caf8685615848565b5060019392505050565b6000610854338484613a61565b60008061287c60055490565b90508061288c5750600092915050565b80611eb260035490565b600061085882613bd1565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c906128e19084903390600401615727565b602060405180830381865afa1580156128fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612922919061573e565b61293e5760405162461bcd60e51b81526004016107a190615760565b61294782613e12565b6001600160a01b0382166000908152601d602052604090819020805460ff19166001179055517fe5526d35f0db491e3e7690717b21c8148a1b5eef07240279db75404df228a59390610a8f90849061541c565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c906129da9084903390600401615727565b602060405180830381865afa1580156129f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1b919061573e565b612a375760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166000908152601c602052604090205460ff16612a6f5760405162461bcd60e51b81526004016107a190615ae3565b6001600160a01b03821660009081526008602052604090205415612ad55760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a204c45444745525f4841535f4e4f4e5f5a45524f5f5354414b450060448201526064016107a1565b6000612ae2836000613fde565b9050600019811415612b325760405162461bcd60e51b815260206004820152601960248201527813125113ce8813115111d15497d393d517d11254d050931151603a1b60448201526064016107a1565b6000839050806001600160a01b031663681fe70c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b99919061573e565b612be15760405162461bcd60e51b81526020600482015260196024820152784c49444f3a204c45444745525f49535f4e4f545f454d50545960381b60448201526064016107a1565b600a805460009190612bf590600190615848565b81548110612c0557612c0561585f565b600091825260209091200154600a80546001600160a01b039092169250829185908110612c3457612c3461585f565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a805480612c7357612c73615b13565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038781168352601c82526040808420805460ff19169055805163118d75f960e11b81529051601b94939287169263231aebf292600480820193918290030181865afa158015612cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d1791906157eb565b81526020808201929092526040908101600090812080546001600160a01b03191690556001600160a01b0388168152601d90925290205460ff1615612d77576001600160a01b0385166000908152601d60205260409020805460ff191690555b6011546040516369c0bc3d60e11b81526001600160a01b039091169063d381787a90612da790889060040161541c565b600060405180830381600087803b158015612dc157600080fd5b505af1158015612dd5573d6000803e3d6000fd5b5050600e5460405163aac271ed60e01b81526001600160a01b03909116925063aac271ed9150612e0990889060040161541c565b600060405180830381600087803b158015612e2357600080fd5b505af1158015612e37573d6000803e3d6000fd5b505050507fd80173368774864e15485d9749961d73c4199e9ef55d044c8ad3427a15ee151785604051612e6a919061541c565b60405180910390a15050505050565b600061086960035490565b60005460ff1615612ea75760405162461bcd60e51b81526004016107a1906157c1565b6000612eb282612870565b905060008111612efb5760405162461bcd60e51b81526020600482015260146024820152734c49444f3a20414d4f554e545f544f4f5f4c4f5760601b60448201526064016107a1565b612f0433613d9f565b811115612f5f5760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a2052454445454d5f414d4f554e545f455843454544535f42414c416044820152624e434560e81b60648201526084016107a1565b612f69338261409f565b508160056000828254612f7c9190615848565b925050819055508160076000828254612f95919061581a565b90915550506019546040516301e9a69560e41b81526001600160a01b0390911690631e9a695090612fcc9033908690600401615b29565b600060405180830381600087803b158015612fe657600080fd5b505af1158015612ffa573d6000803e3d6000fd5b505060405184815260009250339150600080516020615d498339815191529060200160405180910390a360405182815233907f4896181ff8f4543cc00db9fe9b6fb7e6f032b7eb772c72ab1ec1b4d2e03b93699060200160405180910390a25050565b600a54600b54606091600091613073919061581a565b6001600160401b0381111561308a5761308a615832565b6040519080825280602002602001820160405280156130b3578160200160208202803683370190505b50905060005b600a54600b546130c9919061581a565b811015610c1157600b54811061311357600b54600a906130e99083615848565b815481106130f9576130f961585f565b6000918252602090912001546001600160a01b031661313c565b600b81815481106131265761312661585f565b6000918252602090912001546001600160a01b03165b82828151811061314e5761314e61585f565b6001600160a01b03909216602092830291909101909101528061317081615875565b9150506130b9565b336000908152601c602052604090205460ff166131a75760405162461bcd60e51b81526004016107a190615a23565b60408051608081018252601e5461ffff808216835262010000820481166020840152600160201b82048116938301849052600160301b909104166060820181905290916000916131f69161593a565b61ffff1690506000811161320c5761320c615b42565b836005600082825461321e919061581a565b9091555050336000908152600860205260408120805486929061324290849061581a565b9091555050336000908152600960205260408120805486929061326690849061581a565b9091555050602082015160009061327f90612710615b58565b61ffff1661328d8387615a76565b6132979190615aab565b90506000816132a560055490565b6132af9190615848565b905060006132bc60055490565b905081156132e557816132ce60035490565b6132d89085615a76565b6132e29190615aab565b90505b6016546132fb906001600160a01b0316826141c5565b50600084866040015161ffff16836133139190615a76565b61331d9190615aab565b60165460155491925061333d916001600160a01b0391821691168361429b565b601554613353906001600160a01b03168261442e565b601654613372906001600160a01b031661336d8385615848565b61442e565b7f61953b03ced70bb23c53b5a7058e431e3db88cf84a72660faea0849b785c43bd3389896040516133a593929190615a02565b60405180910390a15050505050505050565b336000908152601c602052604090205460ff166133e65760405162461bcd60e51b81526004016107a190615a23565b3360009081526008602090815260408083205460099092529091205461340d90839061581a565b111561345b5760405162461bcd60e51b815260206004820152601d60248201527f4c49444f3a204c45444745525f4e4f545f454e4f5547485f5354414b4500000060448201526064016107a1565b336000908152600960205260408120805483929061347a90849061581a565b9091555050600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906134b19033908590600401615b29565b6020604051808303816000875af11580156134d0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6b919061573e565b600f54604051633bfc46cb60e21b81527fe6f5d3a94b3b2e5137a1b6bff43c8dde49b099cd4958238240e4ab304e4a2b68916001600160a01b03169063eff11b2c906135469084903390600401615727565b602060405180830381865afa158015613563573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613587919061573e565b6135a35760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166135f95760405162461bcd60e51b815260206004820181905260248201527f4c49444f3a20494e434f52524543545f54524541535552595f4144445245535360448201526064016107a1565b50601680546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c9061365c9084903390600401615727565b602060405180830381865afa158015613679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369d919061573e565b6136b95760405162461bcd60e51b81526004016107a190615760565b610e6b82613e12565b600061085882613d9f565b600f54604051633bfc46cb60e21b8152600080516020615d09833981519152916001600160a01b03169063eff11b2c9061370d9084903390600401615727565b602060405180830381865afa15801561372a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374e919061573e565b61376a5760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166137c05760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a20494e434f52524543545f464143544f52595f414444524553530060448201526064016107a1565b50601880546001600160a01b0319166001600160a01b0392909216919091179055565b6011546001600160a01b0316331461383c5760405162461bcd60e51b815260206004820152601c60248201527b2624a2279d102727aa2fa32927a6afa7a920a1a622afa6a0a9aa22a960211b60448201526064016107a1565b601960009054906101000a90046001600160a01b03166001600160a01b0316637b2077276040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561388c57600080fd5b505af11580156138a0573d6000803e3d6000fd5b505050506138ac614467565b565b60005460ff166138f75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016107a1565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051613931919061541c565b60405180910390a1565b60005460ff161561395e5760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b0383166139b05760405162461bcd60e51b8152602060048201526019602482015278415050524f56455f46524f4d5f5a45524f5f4144445245535360381b60448201526064016107a1565b6001600160a01b038216613a005760405162461bcd60e51b8152602060048201526017602482015276415050524f56455f544f5f5a45524f5f4144445245535360481b60448201526064016107a1565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000613a6c82612870565b9050613a7984848361429b565b826001600160a01b0316846001600160a01b0316600080516020615d4983398151915284604051613aac91815260200190565b60405180910390a350505050565b60005b600a54600b54613acd919061581a565b811015613bcb57600b546000908210613b1a57600b54600a90613af09084615848565b81548110613b0057613b0061585f565b6000918252602090912001546001600160a01b0316613b43565b600b8281548110613b2d57613b2d61585f565b6000918252602090912001546001600160a01b03165b60405163416acf8b60e11b81526001600160801b03808816600483015286166024820152604481018590529091506001600160a01b038216906382d59f1690606401600060405180830381600087803b158015613b9f57600080fd5b505af1158015613bb3573d6000803e3d6000fd5b50505050508080613bc390615875565b915050613abd565b50505050565b6000805460ff1615613bf55760405162461bcd60e51b81526004016107a1906157c1565b600c5482600554613c06919061581a565b10613c4f5760405162461bcd60e51b815260206004820152601960248201527804c49444f3a204445504f534954535f4558434545445f43415603c1b60448201526064016107a1565b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90613c8390339030908790600401615a52565b6020604051808303816000875af1158015613ca2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc6919061573e565b5081613d095760405162461bcd60e51b815260206004820152601260248201527113125113ce8816915493d7d1115413d4d25560721b60448201526064016107a1565b6000613d1483612870565b905080613d1e5750815b8260056000828254613d30919061581a565b925050819055508260066000828254613d49919061581a565b90915550613d59905033826141c5565b50613d64338261442e565b60405183815233907f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c49060200160405180910390a292915050565b6001600160a01b031660009081526001602052604090205490565b60005460ff1615613ddd5760405162461bcd60e51b81526004016107a1906157c1565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586139243390565b6001600160a01b0381166000908152601c602052604090205460ff16613e4a5760405162461bcd60e51b81526004016107a190615ae3565b6000613e57826001613fde565b9050600019811415613ea65760405162461bcd60e51b815260206004820152601860248201527713125113ce8813115111d15497d393d517d153905093115160421b60448201526064016107a1565b600b805460009190613eba90600190615848565b81548110613eca57613eca61585f565b600091825260209091200154600b80546001600160a01b039092169250829184908110613ef957613ef961585f565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b805480613f3857613f38615b13565b600082815260208120600019908301810180546001600160a01b03199081169091559201909255600a805460018101825592527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910180549091166001600160a01b0385161790556040517f85accaad76657cef23e292273789ae7a13d87db42feff1d70d4056c20d78d07190613fd190859061541c565b60405180910390a1505050565b60008082613fee57600a54613ff2565b600b545b905060005b818110156140935760008461403357600a82815481106140195761401961585f565b6000918252602090912001546001600160a01b031661405c565b600b82815481106140465761404661585f565b6000918252602090912001546001600160a01b03165b9050856001600160a01b0316816001600160a01b03161415614082575091506108589050565b5061408c81615875565b9050613ff7565b50600019949350505050565b6000805460ff16156140c35760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b0383166141165760405162461bcd60e51b815260206004820152601a6024820152794255524e5f46524f4d5f5448455f5a45524f5f4144445245535360301b60448201526064016107a1565b6001600160a01b0383166000908152600160205260409020548083111561417d5760405162461bcd60e51b815260206004820152601b60248201527a4255524e5f414d4f554e545f455843454544535f42414c414e434560281b60448201526064016107a1565b8261418760035490565b6141919190615848565b600381905591506141a28382615848565b6001600160a01b0390941660009081526001602052604090209390935592915050565b6000805460ff16156141e95760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b03831661423a5760405162461bcd60e51b81526020600482015260186024820152774d494e545f544f5f5448455f5a45524f5f4144445245535360401b60448201526064016107a1565b8161424460035490565b61424e919061581a565b60038190556001600160a01b03841660009081526001602052604090205490915061427a90839061581a565b6001600160a01b039093166000908152600160205260409020929092555090565b60005460ff16156142be5760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b0383166143145760405162461bcd60e51b815260206004820152601e60248201527f5452414e534645525f46524f4d5f5448455f5a45524f5f41444452455353000060448201526064016107a1565b6001600160a01b0382166143695760405162461bcd60e51b815260206004820152601c60248201527b5452414e534645525f544f5f5448455f5a45524f5f4144445245535360201b60448201526064016107a1565b6001600160a01b038316600090815260016020526040902054808211156143d25760405162461bcd60e51b815260206004820152601f60248201527f5452414e534645525f414d4f554e545f455843454544535f42414c414e43450060448201526064016107a1565b6143dc8282615848565b6001600160a01b03808616600090815260016020526040808220939093559085168152205461440c90839061581a565b6001600160a01b03909316600090815260016020526040902092909255505050565b6001600160a01b0382166000600080516020615d4983398151915261445284611e86565b60405190815260200160405180910390a35050565b6000805b600a54600b5461447b919061581a565b81101561462f57600b5460009082106144c857600b54600a9061449e9084615848565b815481106144ae576144ae61585f565b6000918252602090912001546001600160a01b03166144f1565b600b82815481106144db576144db61585f565b6000918252602090912001546001600160a01b03165b6001600160a01b038116600090815260096020908152604080832054600890925290912054919250101561461e576001600160a01b038116600090815260096020908152604080832054600890925282205461454d9190615848565b600654600d546040516370a0823160e01b815292935090916001600160a01b03909116906370a082319061458590309060040161541c565b602060405180830381865afa1580156145a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145c691906157eb565b6145d09190615848565b6145da828661581a565b1161461c576145e9818561581a565b6001600160a01b038316600090815260086020526040812080549296508392909190614616908490615848565b90915550505b505b5061462881615875565b905061446b565b508060066000828254614642919061581a565b909155505060065415158061465957506000600754115b156107b257600a541580159061467157506000600754115b15614685576146816007546147ae565b6007555b600060065411801561469957506000600754115b15614765576000600754600654116146b3576006546146b7565b6007545b905080600660008282546146cb9190615848565b9250508190555080600760008282546146e49190615848565b9091555050600d5460195460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb9261471f929116908590600401615b29565b6020604051808303816000875af115801561473e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614762919061573e565b50505b600b54156107b257600061477a6007546149a9565b6147856006546149a9565b61478f9190615b7b565b905080156147a0576147a081614a13565b506000600681905560075550565b600a54600090806147c1576147c1615b42565b60008060005b8381101561486b57601d6000600a83815481106147e6576147e661585f565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661485b5760086000600a83815481106148295761482961585f565b60009182526020808320909101546001600160a01b03168352820192909252604001902054614858908461581a565b92505b61486481615875565b90506147c7565b508161487a5750929392505050565b60005b8381101561499557601d6000600a838154811061489c5761489c61585f565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661498557600060086000600a84815481106148e1576148e161585f565b60009182526020808320909101546001600160a01b03168352820192909252604001812054915084614913838a615a76565b61491d9190615aab565b905081811161492c578061492e565b815b905061493a8183615848565b60086000600a86815481106149515761495161585f565b60009182526020808320909101546001600160a01b03168352820192909252604001902055614980818561581a565b935050505b61498e81615875565b905061487d565b506149a08186615848565b95945050505050565b6000600160ff1b8210614a0f5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016107a1565b5090565b600b5480614a2357614a23615b42565b6000816001600160401b03811115614a3d57614a3d615832565b604051908082528060200260200182016040528015614a66578160200160208202803683370190505b5090506000826001600160401b03811115614a8357614a83615832565b604051908082528060200260200182016040528015614aac578160200160208202803683370190505b5090506000836001600160401b03811115614ac957614ac9615832565b604051908082528060200260200182016040528015614af2578160200160208202803683370190505b5090506000846001600160401b03811115614b0f57614b0f615832565b604051908082528060200260200182016040528015614b38578160200160208202803683370190505b50905060008060008088614b4a61085e565b614b549190615aab565b90506000805b8a811015614cff57600b8181548110614b7557614b7561585f565b9060005260206000200160009054906101000a90046001600160a01b0316898281518110614ba557614ba561585f565b60200260200101906001600160a01b031690816001600160a01b031681525050600860008a8381518110614bdb57614bdb61585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054888281518110614c1657614c1661585f565b602002602001018181525050600860008a8381518110614c3857614c3861585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054878281518110614c7357614c7361585f565b602002602001018181525050878181518110614c9157614c9161585f565b602002602001015183614ca49190615b7b565b91506000614cb2838e615bba565b1315614cc557614cc28287615c3f565b95505b818a8281518110614cd857614cd861585f565b6020908102919091010152614ced8285615c3f565b9350614cf881615875565b9050614b5a565b5050508060001480614d0f575082155b15614d1f57505050505050505050565b60016000841215614d3a5750600019614d3784615c80565b93505b60005b89811015614e74578160000b898281518110614d5b57614d5b61585f565b60200260200101818151614d6f9190615bba565b90525088516000908a9083908110614d8957614d8961585f565b60200260200101511315614e64576000858c8b8481518110614dad57614dad61585f565b6020026020010151614dbf9190615bba565b614dc99190615c9d565b9050600081898481518110614de057614de061585f565b6020026020010151614df29190615c3f565b905080600860008c8681518110614e0b57614e0b61585f565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555080898481518110614e4a57614e4a61585f565b6020908102919091010152614e5f8287615c3f565b955050505b614e6d81615875565b9050614d3d565b506000614e81848c615b7b565b90506000811315614ee65780600860008a600081518110614ea457614ea461585f565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000828254614edb919061581a565b90915550614fc49050565b6000811215614fc45760005b8a81108015614f015750600082125b15614fc2576000888281518110614f1a57614f1a61585f565b602002602001015190506000811115614fb1576000614f3884615c80565b8211614f445781614f4d565b614f4d84615c80565b905080600860008d8681518110614f6657614f6661585f565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000828254614f9d9190615848565b90915550614fad90508185615c3f565b9350505b50614fbb81615875565b9050614ef2565b505b506000805b8a811015615215576000898281518110614fe557614fe561585f565b60200260200101516001600160a01b031663a5baabf06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561502a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061504e9190615ccb565b6001600160801b0316600960008c858151811061506d5761506d61585f565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546150a09190615848565b90508782815181106150b4576150b461585f565b60200260200101518111801561512057508782815181106150d7576150d761585f565b6020026020010151600860008c85815181106150f5576150f561585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054115b156152045780600860008c858151811061513c5761513c61585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054116151d25787828151811061517c5761517c61585f565b6020026020010151600860008c858151811061519a5761519a61585f565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546151cd9190615848565b6151f7565b8782815181106151e4576151e461585f565b6020026020010151816151f79190615848565b615201908461581a565b92505b5061520e81615875565b9050614fc9565b50801561529757600d5460195460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92615252929116908590600401615b29565b6020604051808303816000875af1158015615271573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615295919061573e565b505b5050505050505050505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b600060208083528351808285015260005b818110156152f8578581018301518582016040015282016152dc565b8181111561530a576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146107b257600080fd5b6000806040838503121561534857600080fd5b823561535381615320565b946020939093013593505050565b60006020828403121561537357600080fd5b8135611ec681615320565b6020808252825182820181905260009190848201906040850190845b818110156153b65783518352928401929184019160010161539a565b50909695505050505050565b6000806000606084860312156153d757600080fd5b83356153e281615320565b925060208401356153f281615320565b929592945050506040919091013590565b60006020828403121561541557600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600060808284031215610c1157600080fd5b6001600160801b03811681146107b257600080fd5b60008060008060008060008060006101208a8c03121561547657600080fd5b893561548181615320565b985060208a013561549181615320565b975060408a01356154a181615320565b965060608a01356154b181615320565b955060808a01356154c181615320565b945060a08a01356154d181615320565b935060c08a01356154e181615320565b925060e08a013591506101008a01356154f981615442565b809150509295985092959850929598565b60008083601f84011261551c57600080fd5b5081356001600160401b0381111561553357600080fd5b6020830191508360208260051b850101111561554e57600080fd5b9250929050565b6000806000806040858703121561556b57600080fd5b84356001600160401b038082111561558257600080fd5b61558e8883890161550a565b909650945060208701359150808211156155a757600080fd5b506155b48782880161550a565b95989497509550505050565b61ffff811681146107b257600080fd5b6000806000606084860312156155e557600080fd5b833592506020840135915060408401356155fe816155c0565b809150509250925092565b60006020828403121561561b57600080fd5b8135611ec681615442565b6000806040838503121561563957600080fd5b50508035926020909101359150565b6000806040838503121561565b57600080fd5b82359150602083013561566d81615320565b809150509250929050565b60008060006060848603121561568d57600080fd5b8335615698816155c0565b925060208401356156a8816155c0565b915060408401356155fe816155c0565b600080604083850312156156cb57600080fd5b82356156d681615320565b9150602083013561566d81615320565b6020808252825182820181905260009190848201906040850190845b818110156153b65783516001600160a01b031683529284019291840191600101615702565b9182526001600160a01b0316602082015260400190565b60006020828403121561575057600080fd5b81518015158114611ec657600080fd5b60208082526012908201527113125113ce8815539055551213d49256915160721b604082015260600190565b600181811c908216806157a057607f821691505b60208210811415610c1157634e487b7160e01b600052602260045260246000fd5b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6000602082840312156157fd57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561582d5761582d615804565b500190565b634e487b7160e01b600052604160045260246000fd5b60008282101561585a5761585a615804565b500390565b634e487b7160e01b600052603260045260246000fd5b600060001982141561588957615889615804565b5060010190565b6000602082840312156158a257600080fd5b8135611ec6816155c0565b81356158b8816155c0565b61ffff8116905081548161ffff19821617835560208401356158d981615442565b6001600160901b03199190911690911760109190911b62010000600160901b031617815560018101604083013561590f81615442565b81546001600160801b0319166001600160801b03919091161790556060919091013560029190910155565b600061ffff80831681851680830382111561595757615957615804565b01949350505050565b6000808335601e1984360301811261597757600080fd5b8301803591506001600160401b0382111561599157600080fd5b6020019150600581901b360382131561554e57600080fd5b6020808252810182905260006001600160fb1b038311156159c957600080fd5b8260051b80856040850137600092016040019182525092915050565b6000602082840312156159f757600080fd5b8151611ec681615320565b6001600160a01b039390931683526020830191909152604082015260600190565b6020808252601590820152742624a2279d102727aa2fa32927a6afa622a223a2a960591b604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000816000190483118215151615615a9057615a90615804565b500290565b634e487b7160e01b600052601260045260246000fd5b600082615aba57615aba615a95565b500490565b60008060408385031215615ad257600080fd5b505080516020909101519092909150565b60208082526016908201527513125113ce8813115111d15497d393d517d193d5539160521b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03929092168252602082015260400190565b634e487b7160e01b600052600160045260246000fd5b600061ffff83811690831681811015615b7357615b73615804565b039392505050565b60008083128015600160ff1b850184121615615b9957615b99615804565b6001600160ff1b0384018313811615615bb457615bb4615804565b50500390565b60006001600160ff1b0381841382841380821686840486111615615be057615be0615804565b600160ff1b6000871282811687830589121615615bff57615bff615804565b60008712925087820587128484161615615c1b57615c1b615804565b87850587128184161615615c3157615c31615804565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615c6157615c61615804565b600160ff1b8390038412811615615c7a57615c7a615804565b50500190565b6000600160ff1b821415615c9657615c96615804565b5060000390565b600082615cac57615cac615a95565b600160ff1b821460001984141615615cc657615cc6615804565b500590565b600060208284031215615cdd57600080fd5b8151611ec68161544256fe585c6e254ec74f8e72b5cff099811ed8721d9039f710d9a1cb67eed6c74aa8279336eb28e461adb6ba7e620f5006a6952a65a21a4db92c2edb104bf7f1c38c63d76e3374742c17bd14ffaf46cd349ec292baf7d8425512fa8fe132557a4c967bddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220464e927a57b5491842c3381984e580b32914e13b803fa68067ac25932e631ea864736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102935760003560e01c8063046f7da21461029857806306fdde03146102a2578063095ea7b3146102c057806318160ddd146102e35780631a813a3c146102f95780631ab81cba146103015780631d55fde41461031457806323b872dd14610329578063240359bc1461033c578063313ce5671461037257806338dee1d314610387578063395093511461039a5780633ca3bca3146103ad5780633fd2c16a146103c057806341c262c5146103d357806347376473146103e657806348c696c0146103f95780634fe28e3a146104025780635c975abb146104155780635e442a9b146104205780635f3f2cac1461044057806361f9c3da1461045357806363ca402d146104665780636a92b586146104795780636e553f65146104a457806370a08231146104b757806373ece435146104ca57806377c96574146104dd5780638456cb5914610505578063866512031461050d5780638ab476bf1461052057806395d89b41146105335780639e0c97041461053b578063a1e206c71461054e578063a457c2d714610561578063a9042441146102e3578063a9059cbb14610574578063b09f532014610587578063b31207f214610590578063b6b55f25146105a3578063cdd8f598146105b6578063d381787a146105c9578063d5002f2e146105dc578063db006a75146105e4578063dbd5edc7146105f7578063dd62ed3e14610600578063df19795614610639578063df6c39fb1461064e578063e100610714610661578063e40b925514610674578063ec70d8001461067d578063f0f4426014610690578063f1447195146106a3578063f339a70d146106c3578063f5eb42dc146106d6578063f7eba420146106e9578063fa597e07146106fc575b600080fd5b6102a0610704565b005b6102aa6107b5565b6040516102b791906152cb565b60405180910390f35b6102d36102ce366004615335565b610847565b60405190151581526020016102b7565b6102eb61085e565b6040519081526020016102b7565b6102a061086e565b6102a061030f366004615361565b610940565b61031c610a9b565b6040516102b7919061537e565b6102d36103373660046153c2565b610c17565b61036561034a366004615403565b6000908152601b60205260409020546001600160a01b031690565b6040516102b7919061541c565b60215460405160ff90911681526020016102b7565b6102a0610395366004615430565b610cbf565b6102d36103a8366004615335565b610e6f565b6102a06103bb366004615457565b610ea6565b601154610365906001600160a01b031681565b6102a06103e1366004615555565b61134f565b6102a06103f4366004615361565b61161b565b6102eb60075481565b6103656104103660046155d0565b611731565b60005460ff166102d3565b6102eb61042e366004615361565b60096020526000908152604090205481565b6102a061044e366004615609565b611bd9565b6102a0610461366004615626565b611d03565b6102eb610474366004615403565b611e86565b601a5461048c906001600160801b031681565b6040516001600160801b0390911681526020016102b7565b6102eb6104b2366004615648565b611ecd565b6102eb6104c5366004615361565b611f33565b6102a06104d8366004615678565b611f41565b6104f06104eb366004615361565b61214b565b604080519283526020830191909152016102b7565b6102a06121c9565b6102a061051b366004615403565b61226e565b6102a061052e366004615361565b61235b565b6102aa61248e565b6102a0610549366004615626565b61249d565b600f54610365906001600160a01b031681565b6102d361056f366004615335565b6127d6565b6102d3610582366004615335565b612863565b6102eb60065481565b6102eb61059e366004615403565b612870565b6102eb6105b1366004615403565b612896565b6102a06105c4366004615361565b6128a1565b6102a06105d7366004615361565b61299a565b6102eb612e79565b6102a06105f2366004615403565b612e84565b6102eb600c5481565b6102eb61060e3660046156b8565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b61064161305d565b6040516102b791906156e6565b6102a061065c366004615626565b613178565b6102a061066f366004615403565b6133b7565b6102eb60055481565b601754610365906001600160a01b031681565b6102a061069e366004615361565b6134f4565b6102eb6106b1366004615361565b60086020526000908152604090205481565b6102a06106d1366004615361565b61361c565b6102eb6106e4366004615361565b6136c2565b6102a06106f7366004615361565b6136cd565b6102a06137e3565b600f54604051633bfc46cb60e21b8152600080516020615d29833981519152916001600160a01b03169063eff11b2c906107449084903390600401615727565b602060405180830381865afa158015610761573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610785919061573e565b6107aa5760405162461bcd60e51b81526004016107a190615760565b60405180910390fd5b6107b26138ae565b50565b6060601f80546107c49061578c565b80601f01602080910402602001604051908101604052809291908181526020018280546107f09061578c565b801561083d5780601f106108125761010080835404028352916020019161083d565b820191906000526020600020905b81548152906001019060200180831161082057829003601f168201915b5050505050905090565b600061085433848461393b565b5060015b92915050565b600061086960055490565b905090565b60005460ff16156108915760405162461bcd60e51b81526004016107a1906157c1565b601954604051630f41a04d60e11b81526000916001600160a01b031690631e83409a906108c290339060040161541c565b6020604051808303816000875af11580156108e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090591906157eb565b60405181815290915033907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a250565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c906109809084903390600401615727565b602060405180830381865afa15801561099d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c1919061573e565b6109dd5760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166000908152601d602052604090205460ff16610a3f5760405162461bcd60e51b815260206004820152601760248201527613125113ce8813115111d15497d393d517d4105554d151604a1b60448201526064016107a1565b6001600160a01b0382166000908152601d602052604090819020805460ff19169055517f8c097d4c8d964b147a04f3a822a31e3aa5a9104dc7db3dde0166a248b8f106c590610a8f90849061541c565b60405180910390a15050565b600a54600b54606091600091610ab1919061581a565b6001600160401b03811115610ac857610ac8615832565b604051908082528060200260200182016040528015610af1578160200160208202803683370190505b50905060005b600a54600b54610b07919061581a565b811015610c1157600b546000908210610b5457600b54600a90610b2a9084615848565b81548110610b3a57610b3a61585f565b6000918252602090912001546001600160a01b0316610b7d565b600b8281548110610b6757610b6761585f565b6000918252602090912001546001600160a01b03165b9050806001600160a01b031663231aebf26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be191906157eb565b838381518110610bf357610bf361585f565b60209081029190910101525080610c0981615875565b915050610af7565b50919050565b6001600160a01b038316600090815260026020908152604080832033845290915281205482811015610c955760405162461bcd60e51b815260206004820152602160248201527f5452414e534645525f414d4f554e545f455843454544535f414c4c4f57414e436044820152604560f81b60648201526084016107a1565b610ca0858585613a61565b610cb48533610caf8685615848565b61393b565b506001949350505050565b600f54604051633bfc46cb60e21b81527f2c204f3ef59cc164f843cf6919920470e37721ba425db7893d02e60cfd0bafdc916001600160a01b03169063eff11b2c90610d119084903390600401615727565b602060405180830381865afa158015610d2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d52919061573e565b610d6e5760405162461bcd60e51b81526004016107a190615760565b6000610d7d6020840184615890565b61ffff1611610dda5760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a204241445f4d41585f56414c494441544f52535f5045525f4c454460448201526223a2a960e91b60648201526084016107a1565b6000826060013511610e2e5760405162461bcd60e51b815260206004820152601e60248201527f4c49444f3a204241445f4d41585f554e4c4f434b494e475f4348554e4b53000060448201526064016107a1565b816012610e3b82826158ad565b50610e6b9050610e516040840160208501615609565b610e616060850160408601615609565b8460600135613aba565b5050565b3360008181526002602090815260408083206001600160a01b03871684529091528120549091610854918590610caf90869061581a565b600454610100900460ff1680610ebf575060045460ff16155b610f225760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016107a1565b600454610100900460ff16158015610f44576004805461ffff19166101011790555b60008311610f855760405162461bcd60e51b815260206004820152600e60248201526d04c49444f3a205a45524f5f4341560941b60448201526064016107a1565b6001600160a01b038916610fda5760405162461bcd60e51b815260206004820152601c60248201527b4c49444f3a20494e434f52524543545f564b534d5f4144445245535360201b60448201526064016107a1565b6001600160a01b03851661103e5760405162461bcd60e51b815260206004820152602560248201527f4c49444f3a20494e434f52524543545f4f5241434c455f4d41535445525f4144604482015264445245535360d81b60648201526084016107a1565b6001600160a01b03841661109f5760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f5749544844524157414c5f4144445245604482015261535360f01b60648201526084016107a1565b6001600160a01b038a166111015760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a20494e434f52524543545f415554484d414e414745525f4144445260448201526245535360e81b60648201526084016107a1565b6001600160a01b0388166111625760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f434f4e54524f4c4c45525f4144445245604482015261535360f01b60648201526084016107a1565b600d80546001600160a01b03808c166001600160a01b031992831617909255600e80548b8416908316179055600f8054928d1692909116919091179055600c83905560c86010556111b16152a4565b6103206111c060c8600061593a565b6111ca919061593a565b61ffff168082526000602083015260c86040808401919091526103206060840152601e805465ffffffffffff1916909217601960231b1761ffff60301b1916601960351b17909155601680546001600160a01b03199081166001600160a01b038b8116919091179092556015805482168c84161790556011805490911691891691821790559051637d774e3160e01b8152637d774e319061126f90309060040161541c565b600060405180830381600087803b15801561128957600080fd5b505af115801561129d573d6000803e3d6000fd5b5050601980546001600160a01b0319166001600160a01b03891690811790915560405163015cda1760e41b81529092506315cda17091506112e290309060040161541c565b600060405180830381600087803b1580156112fc57600080fd5b505af1158015611310573d6000803e3d6000fd5b5050601a80546001600160801b0319166001600160801b038716179055505081159050611343576004805461ff00191690555b50505050505050505050565b600f54604051633bfc46cb60e21b81527fdefdc47e8c8311059971baa7eda778fd22d6ea93a75a917e77534b8ce74fe4f9916001600160a01b03169063eff11b2c906113a19084903390600401615727565b602060405180830381865afa1580156113be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e2919061573e565b6113fe5760405162461bcd60e51b81526004016107a190615760565b8382146114455760405162461bcd60e51b815260206004820152601560248201527413125113ce88125390d3d4949150d517d253941555605a1b60448201526064016107a1565b60005b84811015611613576000601b818888858181106114675761146761585f565b60209081029290920135835250810191909152604001600020546001600160a01b031614156114d65760405162461bcd60e51b815260206004820152601b60248201527a13125113ce88155392d393d5d397d4d51054d217d050d0d3d55395602a1b60448201526064016107a1565b60125461ffff168484838181106114ef576114ef61585f565b90506020028101906115019190615960565b905011156115515760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a2056414c494441544f52535f414d4f554e545f544f4f5f4249470060448201526064016107a1565b601b60008787848181106115675761156761585f565b60209081029290920135835250810191909152604001600020546001600160a01b031663f5330e968585848181106115a1576115a161585f565b90506020028101906115b39190615960565b6040518363ffffffff1660e01b81526004016115d09291906159a9565b600060405180830381600087803b1580156115ea57600080fd5b505af11580156115fe573d6000803e3d6000fd5b505050508061160c90615875565b9050611448565b505050505050565b600f54604051633bfc46cb60e21b8152600080516020615d09833981519152916001600160a01b03169063eff11b2c9061165b9084903390600401615727565b602060405180830381865afa158015611678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169c919061573e565b6116b85760405162461bcd60e51b81526004016107a190615760565b6001600160a01b03821661170e5760405162461bcd60e51b815260206004820152601e60248201527f4c49444f3a20494e434f52524543545f424541434f4e5f41444452455353000060448201526064016107a1565b50601780546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604051633bfc46cb60e21b8152600091600080516020615ce9833981519152916001600160a01b039091169063eff11b2c906117769084903390600401615727565b602060405180830381865afa158015611793573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b7919061573e565b6117d35760405162461bcd60e51b81526004016107a190615760565b6017546001600160a01b031661182b5760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a20554e5350454349464945445f4c45444745525f424541434f4e0060448201526064016107a1565b6018546001600160a01b03166118835760405162461bcd60e51b815260206004820181905260248201527f4c49444f3a20554e5350454349464945445f4c45444745525f464143544f525960448201526064016107a1565b6011546001600160a01b03166118d45760405162461bcd60e51b81526020600482015260166024820152752624a2279d102727afa7a920a1a622afa6a0a9aa22a960511b60448201526064016107a1565b601054600a54600b546118e7919061581a565b1061192f5760405162461bcd60e51b815260206004820152601860248201527713125113ce8813115111d15494d7d413d3d317d31253525560421b60448201526064016107a1565b6000858152601b60205260409020546001600160a01b0316156119915760405162461bcd60e51b815260206004820152601a6024820152794c49444f3a2053544153485f414c52454144595f45584953545360301b60448201526064016107a1565b601854600d54600e5460125460135460145460405163776aecef60e11b8152600481018c9052602481018b90526001600160a01b0395861660448201529385166064850152620100009092046001600160801b0390811660848501521660a483015260c4820152600092919091169063eed5d9de9060e4016020604051808303816000875af1158015611a28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a4c91906159e5565b600b805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b038085166001600160a01b0319928316811790935560008b8152601b6020908152604080832080549095168617909455938152601c90935291819020805460ff191690931790925560115491516327c13a6b60e21b81529293501690639f04e9ac90611af390849060040161541c565b600060405180830381600087803b158015611b0d57600080fd5b505af1158015611b21573d6000803e3d6000fd5b5050600e54604051639632acf760e01b815261ffff88166004820152602481018a90526001600160a01b0385811660448301529091169250639632acf79150606401600060405180830381600087803b158015611b7d57600080fd5b505af1158015611b91573d6000803e3d6000fd5b505050507f4522989a180263bb7fbc1471718de7bdd69a5d36b5d29511958afa11d2e9da04818787604051611bc893929190615a02565b60405180910390a195945050505050565b600f54604051633bfc46cb60e21b8152600080516020615d09833981519152916001600160a01b03169063eff11b2c90611c199084903390600401615727565b602060405180830381865afa158015611c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5a919061573e565b611c765760405162461bcd60e51b81526004016107a190615760565b6000826001600160801b031611611ce05760405162461bcd60e51b815260206004820152602860248201527f4c49444f3a20494e434f52524543545f4d41585f414c4c4f5741424c455f444960448201526746464552454e434560c01b60648201526084016107a1565b50601a80546001600160801b0319166001600160801b0392909216919091179055565b336000908152601c602052604090205460ff16611d325760405162461bcd60e51b81526004016107a190615a23565b8015611de1578060056000828254611d4a919061581a565b925050819055508060066000828254611d63919061581a565b9091555050600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611d9c90339030908690600401615a52565b6020604051808303816000875af1158015611dbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ddf919061573e565b505b3360009081526009602052604081208054849290611e00908490615848565b9091555050600d546019546040516323b872dd60e01b81526001600160a01b03928316926323b872dd92611e3e923392909116908790600401615a52565b6020604051808303816000875af1158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e81919061573e565b505050565b600080611e9260035490565b905060035460001415611ea85750600092915050565b80611eb260055490565b611ebc9085615a76565b611ec69190615aab565b9392505050565b600080611ed984613bd1565b604080513381526001600160a01b0386166020820152908101869052606081018290529091507f90f46099733ed637df811df4fcc5cae4961192ca04f36da9ab64b4dd8dc9b7f59060800160405180910390a19392505050565b600061085861047483613d9f565b600f54604051633bfc46cb60e21b81527f0fc26914248bb9568b0afb008dd993637f6fb6bdc9598c222c68a21e90ca53c1916001600160a01b03169063eff11b2c90611f939084903390600401615727565b602060405180830381865afa158015611fb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd4919061573e565b611ff05760405162461bcd60e51b81526004016107a190615760565b611ff86152a4565b82612003868661593a565b61200d919061593a565b61ffff1680825261271010801590612037575060008461ffff161180612037575060008361ffff16115b801561204857506127108561ffff16105b61208c5760405162461bcd60e51b815260206004820152601560248201527404c49444f3a204645455f444f4e545f4144445f555605c1b60448201526064016107a1565b80516040805161ffff92831681528783166020820152868316818301529185166060830152517fb01998f6d1382c5b6c7a4b477769ce2ffbbb91adc291994665b24def9a47e4509181900360800190a161ffff9283166040820181905294831660208201819052938316606082018190529051601e80549190941663ffffffff1990911617620100009094029390931763ffffffff60201b1916600160201b90940261ffff60301b191693909317600160301b90920291909117905550565b601954604051630aff799160e41b815260009182916001600160a01b039091169063aff799109061218090869060040161541c565b6040805180830381865afa15801561219c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121c09190615abf565b91509150915091565b600f54604051633bfc46cb60e21b8152600080516020615d29833981519152916001600160a01b03169063eff11b2c906122099084903390600401615727565b602060405180830381865afa158015612226573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224a919061573e565b6122665760405162461bcd60e51b81526004016107a190615760565b6107b2613dba565b600f54604051633bfc46cb60e21b8152600080516020615d29833981519152916001600160a01b03169063eff11b2c906122ae9084903390600401615727565b602060405180830381865afa1580156122cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ef919061573e565b61230b5760405162461bcd60e51b81526004016107a190615760565b600082116123555760405162461bcd60e51b815260206004820152601760248201527604c49444f3a20494e434f52524543545f4e45575f43415604c1b60448201526064016107a1565b50600c55565b600f54604051633bfc46cb60e21b81527fbd1ecc6a842ff1f2601eedd75a87543c45753bbba85c665c9f8870558fb3a2cf916001600160a01b03169063eff11b2c906123ad9084903390600401615727565b602060405180830381865afa1580156123ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ee919061573e565b61240a5760405162461bcd60e51b81526004016107a190615760565b6001600160a01b03821661246b5760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f444556454c4f504552535f4144445245604482015261535360f01b60648201526084016107a1565b50601580546001600160a01b0319166001600160a01b0392909216919091179055565b6060602080546107c49061578c565b336000908152601c602052604090205460ff166124cc5760405162461bcd60e51b81526004016107a190615a23565b601954604080516301b7603360e11b815290516000926001600160a01b03169163036ec0669160048083019260209291908290030181865afa158015612516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253a91906157eb565b90506000601960009054906101000a90046001600160a01b03166001600160a01b0316633dbfe6cb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612591573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125b591906157eb565b600d546019546040516370a0823160e01b81529293506000926001600160a01b03928316926370a08231926125ef9291169060040161541c565b602060405180830381865afa15801561260c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263091906157eb565b905060008161263f848661581a565b111561265c5761264f8383615848565b6126599085615848565b90505b60008160055461266c919061581a565b6005546126799089615a76565b6126839190615aab565b905080600560008282546126979190615848565b90915550600090506126a98289615848565b111561271b576019546001600160a01b0316634f5b636c6126ca838a615848565b6040518263ffffffff1660e01b81526004016126e891815260200190565b600060405180830381600087803b15801561270257600080fd5b505af1158015612716573d6000803e3d6000fd5b505050505b336000908152600860205260409020548111156127475733600090815260086020526040902054612749565b805b3360009081526008602052604081208054909190612768908490615848565b9091555050336000908152600960205260408120805489929061278c908490615848565b90915550506040517f28457ba4ae46aeb68ba5c1a1c15506fb3212bfff27da04dee70b81023a9ebc04906127c59033908a908a90615a02565b60405180910390a150505050505050565b3360009081526002602090815260408083206001600160a01b03861684529091528120548281101561284a5760405162461bcd60e51b815260206004820152601e60248201527f4445435245415345445f414c4c4f57414e43455f42454c4f575f5a45524f000060448201526064016107a1565b6128593385610caf8685615848565b5060019392505050565b6000610854338484613a61565b60008061287c60055490565b90508061288c5750600092915050565b80611eb260035490565b600061085882613bd1565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c906128e19084903390600401615727565b602060405180830381865afa1580156128fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612922919061573e565b61293e5760405162461bcd60e51b81526004016107a190615760565b61294782613e12565b6001600160a01b0382166000908152601d602052604090819020805460ff19166001179055517fe5526d35f0db491e3e7690717b21c8148a1b5eef07240279db75404df228a59390610a8f90849061541c565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c906129da9084903390600401615727565b602060405180830381865afa1580156129f7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a1b919061573e565b612a375760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166000908152601c602052604090205460ff16612a6f5760405162461bcd60e51b81526004016107a190615ae3565b6001600160a01b03821660009081526008602052604090205415612ad55760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a204c45444745525f4841535f4e4f4e5f5a45524f5f5354414b450060448201526064016107a1565b6000612ae2836000613fde565b9050600019811415612b325760405162461bcd60e51b815260206004820152601960248201527813125113ce8813115111d15497d393d517d11254d050931151603a1b60448201526064016107a1565b6000839050806001600160a01b031663681fe70c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b99919061573e565b612be15760405162461bcd60e51b81526020600482015260196024820152784c49444f3a204c45444745525f49535f4e4f545f454d50545960381b60448201526064016107a1565b600a805460009190612bf590600190615848565b81548110612c0557612c0561585f565b600091825260209091200154600a80546001600160a01b039092169250829185908110612c3457612c3461585f565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a805480612c7357612c73615b13565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038781168352601c82526040808420805460ff19169055805163118d75f960e11b81529051601b94939287169263231aebf292600480820193918290030181865afa158015612cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d1791906157eb565b81526020808201929092526040908101600090812080546001600160a01b03191690556001600160a01b0388168152601d90925290205460ff1615612d77576001600160a01b0385166000908152601d60205260409020805460ff191690555b6011546040516369c0bc3d60e11b81526001600160a01b039091169063d381787a90612da790889060040161541c565b600060405180830381600087803b158015612dc157600080fd5b505af1158015612dd5573d6000803e3d6000fd5b5050600e5460405163aac271ed60e01b81526001600160a01b03909116925063aac271ed9150612e0990889060040161541c565b600060405180830381600087803b158015612e2357600080fd5b505af1158015612e37573d6000803e3d6000fd5b505050507fd80173368774864e15485d9749961d73c4199e9ef55d044c8ad3427a15ee151785604051612e6a919061541c565b60405180910390a15050505050565b600061086960035490565b60005460ff1615612ea75760405162461bcd60e51b81526004016107a1906157c1565b6000612eb282612870565b905060008111612efb5760405162461bcd60e51b81526020600482015260146024820152734c49444f3a20414d4f554e545f544f4f5f4c4f5760601b60448201526064016107a1565b612f0433613d9f565b811115612f5f5760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a2052454445454d5f414d4f554e545f455843454544535f42414c416044820152624e434560e81b60648201526084016107a1565b612f69338261409f565b508160056000828254612f7c9190615848565b925050819055508160076000828254612f95919061581a565b90915550506019546040516301e9a69560e41b81526001600160a01b0390911690631e9a695090612fcc9033908690600401615b29565b600060405180830381600087803b158015612fe657600080fd5b505af1158015612ffa573d6000803e3d6000fd5b505060405184815260009250339150600080516020615d498339815191529060200160405180910390a360405182815233907f4896181ff8f4543cc00db9fe9b6fb7e6f032b7eb772c72ab1ec1b4d2e03b93699060200160405180910390a25050565b600a54600b54606091600091613073919061581a565b6001600160401b0381111561308a5761308a615832565b6040519080825280602002602001820160405280156130b3578160200160208202803683370190505b50905060005b600a54600b546130c9919061581a565b811015610c1157600b54811061311357600b54600a906130e99083615848565b815481106130f9576130f961585f565b6000918252602090912001546001600160a01b031661313c565b600b81815481106131265761312661585f565b6000918252602090912001546001600160a01b03165b82828151811061314e5761314e61585f565b6001600160a01b03909216602092830291909101909101528061317081615875565b9150506130b9565b336000908152601c602052604090205460ff166131a75760405162461bcd60e51b81526004016107a190615a23565b60408051608081018252601e5461ffff808216835262010000820481166020840152600160201b82048116938301849052600160301b909104166060820181905290916000916131f69161593a565b61ffff1690506000811161320c5761320c615b42565b836005600082825461321e919061581a565b9091555050336000908152600860205260408120805486929061324290849061581a565b9091555050336000908152600960205260408120805486929061326690849061581a565b9091555050602082015160009061327f90612710615b58565b61ffff1661328d8387615a76565b6132979190615aab565b90506000816132a560055490565b6132af9190615848565b905060006132bc60055490565b905081156132e557816132ce60035490565b6132d89085615a76565b6132e29190615aab565b90505b6016546132fb906001600160a01b0316826141c5565b50600084866040015161ffff16836133139190615a76565b61331d9190615aab565b60165460155491925061333d916001600160a01b0391821691168361429b565b601554613353906001600160a01b03168261442e565b601654613372906001600160a01b031661336d8385615848565b61442e565b7f61953b03ced70bb23c53b5a7058e431e3db88cf84a72660faea0849b785c43bd3389896040516133a593929190615a02565b60405180910390a15050505050505050565b336000908152601c602052604090205460ff166133e65760405162461bcd60e51b81526004016107a190615a23565b3360009081526008602090815260408083205460099092529091205461340d90839061581a565b111561345b5760405162461bcd60e51b815260206004820152601d60248201527f4c49444f3a204c45444745525f4e4f545f454e4f5547485f5354414b4500000060448201526064016107a1565b336000908152600960205260408120805483929061347a90849061581a565b9091555050600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906134b19033908590600401615b29565b6020604051808303816000875af11580156134d0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6b919061573e565b600f54604051633bfc46cb60e21b81527fe6f5d3a94b3b2e5137a1b6bff43c8dde49b099cd4958238240e4ab304e4a2b68916001600160a01b03169063eff11b2c906135469084903390600401615727565b602060405180830381865afa158015613563573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613587919061573e565b6135a35760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166135f95760405162461bcd60e51b815260206004820181905260248201527f4c49444f3a20494e434f52524543545f54524541535552595f4144445245535360448201526064016107a1565b50601680546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604051633bfc46cb60e21b8152600080516020615ce9833981519152916001600160a01b03169063eff11b2c9061365c9084903390600401615727565b602060405180830381865afa158015613679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369d919061573e565b6136b95760405162461bcd60e51b81526004016107a190615760565b610e6b82613e12565b600061085882613d9f565b600f54604051633bfc46cb60e21b8152600080516020615d09833981519152916001600160a01b03169063eff11b2c9061370d9084903390600401615727565b602060405180830381865afa15801561372a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374e919061573e565b61376a5760405162461bcd60e51b81526004016107a190615760565b6001600160a01b0382166137c05760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a20494e434f52524543545f464143544f52595f414444524553530060448201526064016107a1565b50601880546001600160a01b0319166001600160a01b0392909216919091179055565b6011546001600160a01b0316331461383c5760405162461bcd60e51b815260206004820152601c60248201527b2624a2279d102727aa2fa32927a6afa7a920a1a622afa6a0a9aa22a960211b60448201526064016107a1565b601960009054906101000a90046001600160a01b03166001600160a01b0316637b2077276040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561388c57600080fd5b505af11580156138a0573d6000803e3d6000fd5b505050506138ac614467565b565b60005460ff166138f75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016107a1565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051613931919061541c565b60405180910390a1565b60005460ff161561395e5760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b0383166139b05760405162461bcd60e51b8152602060048201526019602482015278415050524f56455f46524f4d5f5a45524f5f4144445245535360381b60448201526064016107a1565b6001600160a01b038216613a005760405162461bcd60e51b8152602060048201526017602482015276415050524f56455f544f5f5a45524f5f4144445245535360481b60448201526064016107a1565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000613a6c82612870565b9050613a7984848361429b565b826001600160a01b0316846001600160a01b0316600080516020615d4983398151915284604051613aac91815260200190565b60405180910390a350505050565b60005b600a54600b54613acd919061581a565b811015613bcb57600b546000908210613b1a57600b54600a90613af09084615848565b81548110613b0057613b0061585f565b6000918252602090912001546001600160a01b0316613b43565b600b8281548110613b2d57613b2d61585f565b6000918252602090912001546001600160a01b03165b60405163416acf8b60e11b81526001600160801b03808816600483015286166024820152604481018590529091506001600160a01b038216906382d59f1690606401600060405180830381600087803b158015613b9f57600080fd5b505af1158015613bb3573d6000803e3d6000fd5b50505050508080613bc390615875565b915050613abd565b50505050565b6000805460ff1615613bf55760405162461bcd60e51b81526004016107a1906157c1565b600c5482600554613c06919061581a565b10613c4f5760405162461bcd60e51b815260206004820152601960248201527804c49444f3a204445504f534954535f4558434545445f43415603c1b60448201526064016107a1565b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90613c8390339030908790600401615a52565b6020604051808303816000875af1158015613ca2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc6919061573e565b5081613d095760405162461bcd60e51b815260206004820152601260248201527113125113ce8816915493d7d1115413d4d25560721b60448201526064016107a1565b6000613d1483612870565b905080613d1e5750815b8260056000828254613d30919061581a565b925050819055508260066000828254613d49919061581a565b90915550613d59905033826141c5565b50613d64338261442e565b60405183815233907f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c49060200160405180910390a292915050565b6001600160a01b031660009081526001602052604090205490565b60005460ff1615613ddd5760405162461bcd60e51b81526004016107a1906157c1565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586139243390565b6001600160a01b0381166000908152601c602052604090205460ff16613e4a5760405162461bcd60e51b81526004016107a190615ae3565b6000613e57826001613fde565b9050600019811415613ea65760405162461bcd60e51b815260206004820152601860248201527713125113ce8813115111d15497d393d517d153905093115160421b60448201526064016107a1565b600b805460009190613eba90600190615848565b81548110613eca57613eca61585f565b600091825260209091200154600b80546001600160a01b039092169250829184908110613ef957613ef961585f565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b805480613f3857613f38615b13565b600082815260208120600019908301810180546001600160a01b03199081169091559201909255600a805460018101825592527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910180549091166001600160a01b0385161790556040517f85accaad76657cef23e292273789ae7a13d87db42feff1d70d4056c20d78d07190613fd190859061541c565b60405180910390a1505050565b60008082613fee57600a54613ff2565b600b545b905060005b818110156140935760008461403357600a82815481106140195761401961585f565b6000918252602090912001546001600160a01b031661405c565b600b82815481106140465761404661585f565b6000918252602090912001546001600160a01b03165b9050856001600160a01b0316816001600160a01b03161415614082575091506108589050565b5061408c81615875565b9050613ff7565b50600019949350505050565b6000805460ff16156140c35760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b0383166141165760405162461bcd60e51b815260206004820152601a6024820152794255524e5f46524f4d5f5448455f5a45524f5f4144445245535360301b60448201526064016107a1565b6001600160a01b0383166000908152600160205260409020548083111561417d5760405162461bcd60e51b815260206004820152601b60248201527a4255524e5f414d4f554e545f455843454544535f42414c414e434560281b60448201526064016107a1565b8261418760035490565b6141919190615848565b600381905591506141a28382615848565b6001600160a01b0390941660009081526001602052604090209390935592915050565b6000805460ff16156141e95760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b03831661423a5760405162461bcd60e51b81526020600482015260186024820152774d494e545f544f5f5448455f5a45524f5f4144445245535360401b60448201526064016107a1565b8161424460035490565b61424e919061581a565b60038190556001600160a01b03841660009081526001602052604090205490915061427a90839061581a565b6001600160a01b039093166000908152600160205260409020929092555090565b60005460ff16156142be5760405162461bcd60e51b81526004016107a1906157c1565b6001600160a01b0383166143145760405162461bcd60e51b815260206004820152601e60248201527f5452414e534645525f46524f4d5f5448455f5a45524f5f41444452455353000060448201526064016107a1565b6001600160a01b0382166143695760405162461bcd60e51b815260206004820152601c60248201527b5452414e534645525f544f5f5448455f5a45524f5f4144445245535360201b60448201526064016107a1565b6001600160a01b038316600090815260016020526040902054808211156143d25760405162461bcd60e51b815260206004820152601f60248201527f5452414e534645525f414d4f554e545f455843454544535f42414c414e43450060448201526064016107a1565b6143dc8282615848565b6001600160a01b03808616600090815260016020526040808220939093559085168152205461440c90839061581a565b6001600160a01b03909316600090815260016020526040902092909255505050565b6001600160a01b0382166000600080516020615d4983398151915261445284611e86565b60405190815260200160405180910390a35050565b6000805b600a54600b5461447b919061581a565b81101561462f57600b5460009082106144c857600b54600a9061449e9084615848565b815481106144ae576144ae61585f565b6000918252602090912001546001600160a01b03166144f1565b600b82815481106144db576144db61585f565b6000918252602090912001546001600160a01b03165b6001600160a01b038116600090815260096020908152604080832054600890925290912054919250101561461e576001600160a01b038116600090815260096020908152604080832054600890925282205461454d9190615848565b600654600d546040516370a0823160e01b815292935090916001600160a01b03909116906370a082319061458590309060040161541c565b602060405180830381865afa1580156145a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145c691906157eb565b6145d09190615848565b6145da828661581a565b1161461c576145e9818561581a565b6001600160a01b038316600090815260086020526040812080549296508392909190614616908490615848565b90915550505b505b5061462881615875565b905061446b565b508060066000828254614642919061581a565b909155505060065415158061465957506000600754115b156107b257600a541580159061467157506000600754115b15614685576146816007546147ae565b6007555b600060065411801561469957506000600754115b15614765576000600754600654116146b3576006546146b7565b6007545b905080600660008282546146cb9190615848565b9250508190555080600760008282546146e49190615848565b9091555050600d5460195460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb9261471f929116908590600401615b29565b6020604051808303816000875af115801561473e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614762919061573e565b50505b600b54156107b257600061477a6007546149a9565b6147856006546149a9565b61478f9190615b7b565b905080156147a0576147a081614a13565b506000600681905560075550565b600a54600090806147c1576147c1615b42565b60008060005b8381101561486b57601d6000600a83815481106147e6576147e661585f565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661485b5760086000600a83815481106148295761482961585f565b60009182526020808320909101546001600160a01b03168352820192909252604001902054614858908461581a565b92505b61486481615875565b90506147c7565b508161487a5750929392505050565b60005b8381101561499557601d6000600a838154811061489c5761489c61585f565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661498557600060086000600a84815481106148e1576148e161585f565b60009182526020808320909101546001600160a01b03168352820192909252604001812054915084614913838a615a76565b61491d9190615aab565b905081811161492c578061492e565b815b905061493a8183615848565b60086000600a86815481106149515761495161585f565b60009182526020808320909101546001600160a01b03168352820192909252604001902055614980818561581a565b935050505b61498e81615875565b905061487d565b506149a08186615848565b95945050505050565b6000600160ff1b8210614a0f5760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b60648201526084016107a1565b5090565b600b5480614a2357614a23615b42565b6000816001600160401b03811115614a3d57614a3d615832565b604051908082528060200260200182016040528015614a66578160200160208202803683370190505b5090506000826001600160401b03811115614a8357614a83615832565b604051908082528060200260200182016040528015614aac578160200160208202803683370190505b5090506000836001600160401b03811115614ac957614ac9615832565b604051908082528060200260200182016040528015614af2578160200160208202803683370190505b5090506000846001600160401b03811115614b0f57614b0f615832565b604051908082528060200260200182016040528015614b38578160200160208202803683370190505b50905060008060008088614b4a61085e565b614b549190615aab565b90506000805b8a811015614cff57600b8181548110614b7557614b7561585f565b9060005260206000200160009054906101000a90046001600160a01b0316898281518110614ba557614ba561585f565b60200260200101906001600160a01b031690816001600160a01b031681525050600860008a8381518110614bdb57614bdb61585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054888281518110614c1657614c1661585f565b602002602001018181525050600860008a8381518110614c3857614c3861585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054878281518110614c7357614c7361585f565b602002602001018181525050878181518110614c9157614c9161585f565b602002602001015183614ca49190615b7b565b91506000614cb2838e615bba565b1315614cc557614cc28287615c3f565b95505b818a8281518110614cd857614cd861585f565b6020908102919091010152614ced8285615c3f565b9350614cf881615875565b9050614b5a565b5050508060001480614d0f575082155b15614d1f57505050505050505050565b60016000841215614d3a5750600019614d3784615c80565b93505b60005b89811015614e74578160000b898281518110614d5b57614d5b61585f565b60200260200101818151614d6f9190615bba565b90525088516000908a9083908110614d8957614d8961585f565b60200260200101511315614e64576000858c8b8481518110614dad57614dad61585f565b6020026020010151614dbf9190615bba565b614dc99190615c9d565b9050600081898481518110614de057614de061585f565b6020026020010151614df29190615c3f565b905080600860008c8681518110614e0b57614e0b61585f565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555080898481518110614e4a57614e4a61585f565b6020908102919091010152614e5f8287615c3f565b955050505b614e6d81615875565b9050614d3d565b506000614e81848c615b7b565b90506000811315614ee65780600860008a600081518110614ea457614ea461585f565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000828254614edb919061581a565b90915550614fc49050565b6000811215614fc45760005b8a81108015614f015750600082125b15614fc2576000888281518110614f1a57614f1a61585f565b602002602001015190506000811115614fb1576000614f3884615c80565b8211614f445781614f4d565b614f4d84615c80565b905080600860008d8681518110614f6657614f6661585f565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000828254614f9d9190615848565b90915550614fad90508185615c3f565b9350505b50614fbb81615875565b9050614ef2565b505b506000805b8a811015615215576000898281518110614fe557614fe561585f565b60200260200101516001600160a01b031663a5baabf06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561502a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061504e9190615ccb565b6001600160801b0316600960008c858151811061506d5761506d61585f565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546150a09190615848565b90508782815181106150b4576150b461585f565b60200260200101518111801561512057508782815181106150d7576150d761585f565b6020026020010151600860008c85815181106150f5576150f561585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054115b156152045780600860008c858151811061513c5761513c61585f565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054116151d25787828151811061517c5761517c61585f565b6020026020010151600860008c858151811061519a5761519a61585f565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546151cd9190615848565b6151f7565b8782815181106151e4576151e461585f565b6020026020010151816151f79190615848565b615201908461581a565b92505b5061520e81615875565b9050614fc9565b50801561529757600d5460195460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92615252929116908590600401615b29565b6020604051808303816000875af1158015615271573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190615295919061573e565b505b5050505050505050505050565b60408051608081018252600080825260208201819052918101829052606081019190915290565b600060208083528351808285015260005b818110156152f8578581018301518582016040015282016152dc565b8181111561530a576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b03811681146107b257600080fd5b6000806040838503121561534857600080fd5b823561535381615320565b946020939093013593505050565b60006020828403121561537357600080fd5b8135611ec681615320565b6020808252825182820181905260009190848201906040850190845b818110156153b65783518352928401929184019160010161539a565b50909695505050505050565b6000806000606084860312156153d757600080fd5b83356153e281615320565b925060208401356153f281615320565b929592945050506040919091013590565b60006020828403121561541557600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600060808284031215610c1157600080fd5b6001600160801b03811681146107b257600080fd5b60008060008060008060008060006101208a8c03121561547657600080fd5b893561548181615320565b985060208a013561549181615320565b975060408a01356154a181615320565b965060608a01356154b181615320565b955060808a01356154c181615320565b945060a08a01356154d181615320565b935060c08a01356154e181615320565b925060e08a013591506101008a01356154f981615442565b809150509295985092959850929598565b60008083601f84011261551c57600080fd5b5081356001600160401b0381111561553357600080fd5b6020830191508360208260051b850101111561554e57600080fd5b9250929050565b6000806000806040858703121561556b57600080fd5b84356001600160401b038082111561558257600080fd5b61558e8883890161550a565b909650945060208701359150808211156155a757600080fd5b506155b48782880161550a565b95989497509550505050565b61ffff811681146107b257600080fd5b6000806000606084860312156155e557600080fd5b833592506020840135915060408401356155fe816155c0565b809150509250925092565b60006020828403121561561b57600080fd5b8135611ec681615442565b6000806040838503121561563957600080fd5b50508035926020909101359150565b6000806040838503121561565b57600080fd5b82359150602083013561566d81615320565b809150509250929050565b60008060006060848603121561568d57600080fd5b8335615698816155c0565b925060208401356156a8816155c0565b915060408401356155fe816155c0565b600080604083850312156156cb57600080fd5b82356156d681615320565b9150602083013561566d81615320565b6020808252825182820181905260009190848201906040850190845b818110156153b65783516001600160a01b031683529284019291840191600101615702565b9182526001600160a01b0316602082015260400190565b60006020828403121561575057600080fd5b81518015158114611ec657600080fd5b60208082526012908201527113125113ce8815539055551213d49256915160721b604082015260600190565b600181811c908216806157a057607f821691505b60208210811415610c1157634e487b7160e01b600052602260045260246000fd5b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6000602082840312156157fd57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561582d5761582d615804565b500190565b634e487b7160e01b600052604160045260246000fd5b60008282101561585a5761585a615804565b500390565b634e487b7160e01b600052603260045260246000fd5b600060001982141561588957615889615804565b5060010190565b6000602082840312156158a257600080fd5b8135611ec6816155c0565b81356158b8816155c0565b61ffff8116905081548161ffff19821617835560208401356158d981615442565b6001600160901b03199190911690911760109190911b62010000600160901b031617815560018101604083013561590f81615442565b81546001600160801b0319166001600160801b03919091161790556060919091013560029190910155565b600061ffff80831681851680830382111561595757615957615804565b01949350505050565b6000808335601e1984360301811261597757600080fd5b8301803591506001600160401b0382111561599157600080fd5b6020019150600581901b360382131561554e57600080fd5b6020808252810182905260006001600160fb1b038311156159c957600080fd5b8260051b80856040850137600092016040019182525092915050565b6000602082840312156159f757600080fd5b8151611ec681615320565b6001600160a01b039390931683526020830191909152604082015260600190565b6020808252601590820152742624a2279d102727aa2fa32927a6afa622a223a2a960591b604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000816000190483118215151615615a9057615a90615804565b500290565b634e487b7160e01b600052601260045260246000fd5b600082615aba57615aba615a95565b500490565b60008060408385031215615ad257600080fd5b505080516020909101519092909150565b60208082526016908201527513125113ce8813115111d15497d393d517d193d5539160521b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03929092168252602082015260400190565b634e487b7160e01b600052600160045260246000fd5b600061ffff83811690831681811015615b7357615b73615804565b039392505050565b60008083128015600160ff1b850184121615615b9957615b99615804565b6001600160ff1b0384018313811615615bb457615bb4615804565b50500390565b60006001600160ff1b0381841382841380821686840486111615615be057615be0615804565b600160ff1b6000871282811687830589121615615bff57615bff615804565b60008712925087820587128484161615615c1b57615c1b615804565b87850587128184161615615c3157615c31615804565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615c6157615c61615804565b600160ff1b8390038412811615615c7a57615c7a615804565b50500190565b6000600160ff1b821415615c9657615c96615804565b5060000390565b600082615cac57615cac615a95565b600160ff1b821460001984141615615cc657615cc6615804565b500590565b600060208284031215615cdd57600080fd5b8151611ec68161544256fe585c6e254ec74f8e72b5cff099811ed8721d9039f710d9a1cb67eed6c74aa8279336eb28e461adb6ba7e620f5006a6952a65a21a4db92c2edb104bf7f1c38c63d76e3374742c17bd14ffaf46cd349ec292baf7d8425512fa8fe132557a4c967bddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220464e927a57b5491842c3381984e580b32914e13b803fa68067ac25932e631ea864736f6c634300080a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.