Contract Overview
Balance:
0 GLMR
GLMR Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0x3259c6ed0b7cc6cdfda8b590d4dd16c97913f4fb7e8cfdbcaab0859866597490 | 0x60806040 | 1384192 | 330 days 17 mins ago | Lido Staked Polkadot: Deployer | IN | Create: Lido | 0 GLMR | 0.5363017 |
[ Download CSV Export ]
Contract Name:
Lido
Compiler Version
v0.8.13+commit.abaa5c0e
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 ); // sum of all deposits and rewards uint256 public fundRaisedBalance; // haven't executed buffrered deposits uint256 public bufferedDeposits; // haven't executed buffrered redeems uint256 public bufferedRedeems; // Ledger target stakes mapping(address => uint256) public ledgerStake; // Ledger borrow 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 */ 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) { uint256 waitingToUnbonding = 0; uint256 readyToClaim = 0; (waitingToUnbonding, readyToClaim) = IWithdrawal(WITHDRAWAL).getRedeemStatus(_holder); return (waitingToUnbonding, readyToClaim); } /** * @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; i++) { _stashes[i] = bytes32(ILedger(enabledLedgers[i]).stashAccount()); } for (uint i = 0; i < disabledLedgers.length; i++) { _stashes[enabledLedgers.length + i] = bytes32(ILedger(disabledLedgers[i]).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; i++) { _ledgers[i] = enabledLedgers[i]; } for (uint i = 0; i < disabledLedgers.length; i++) { _ledgers[enabledLedgers.length + i] = disabledLedgers[i]; } 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 Returns total fee basis points */ function getFee() external view returns (uint16){ return FEE.total; } /** * @notice Returns all fees basis points */ function getAllFees() external view returns (Types.Fee memory){ return FEE; } /** * @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); 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]); } } /** * @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) external whenNotPaused returns (uint256) { require(fundRaisedBalance + _amount < depositCap, "LIDO: DEPOSITS_EXCEED_CAP"); VKSM.transferFrom(msg.sender, address(this), _amount); uint256 shares = _submit(_amount); 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 ledger to LIDO. Can be called only from ledger * @param _amount - amount of transfered vKSM */ // NOTE: DEPRECATED // function transferFromLedger(uint256 _amount) external { // require(ledgerByAddress[msg.sender], "LIDO: NOT_FROM_LEDGER"); // if (_amount > ledgerBorrow[msg.sender]) { // some donations // uint256 excess = _amount - ledgerBorrow[msg.sender]; // fundRaisedBalance += excess; //just distribute it as rewards // bufferedDeposits += excess; // ledgerBorrow[msg.sender] = 0; // VKSM.transferFrom(msg.sender, address(this), excess); // VKSM.transferFrom(msg.sender, WITHDRAWAL, _amount - excess); // } // else { // 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 { 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; i++) { ILedger(enabledLedgers[i]).setRelaySpecs(_minNominatorBalance, _minimumBalance, _maxUnlockingChunks); } for (uint i = 0; i < disabledLedgers.length; i++) { ILedger(disabledLedgers[i]).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 = _findEnabledLedger(_ledgerAddress); 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 Process user deposit, mints stKSM and increase the pool buffer * @return amount of stKSM shares generated */ function _submit(uint256 _deposit) internal returns (uint256) { address sender = msg.sender; require(_deposit != 0, "LIDO: ZERO_DEPOSIT"); uint256 sharesAmount = getSharesByPooledKSM(_deposit); if (sharesAmount == 0) { // totalPooledKSM is 0: either the first-ever deposit or complete slashing // assume that shares correspond to KSM as 1-to-1 sharesAmount = _deposit; } fundRaisedBalance += _deposit; bufferedDeposits += _deposit; _mintShares(sender, sharesAmount); _emitTransferAfterMintingShares(sender, sharesAmount); return sharesAmount; } /** * @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 ledger index by given address * @return enabled ledger index or uint256_max if not found */ function _findEnabledLedger(address _ledgerAddress) internal view returns(uint256) { for (uint256 i = 0; i < enabledLedgers.length; ++i) { if (enabledLedgers[i] == _ledgerAddress) { return i; } } return type(uint256).max; } /** * @notice Returns disabled ledger index by given address * @return disabled ledger index or uint256_max if not found */ function _findDisabledLedger(address _ledgerAddress) internal view returns(uint256) { for (uint256 i = 0; i < disabledLedgers.length; ++i) { if (disabledLedgers[i] == _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": 10 }, "libraries": { "Lido.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"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":"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"}],"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":"getAllFees","outputs":[{"components":[{"internalType":"uint16","name":"total","type":"uint16"},{"internalType":"uint16","name":"operators","type":"uint16"},{"internalType":"uint16","name":"developers","type":"uint16"},{"internalType":"uint16","name":"treasury","type":"uint16"}],"internalType":"struct Types.Fee","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":"string","name":"__name","type":"string"},{"internalType":"string","name":"__symbol","type":"string"},{"internalType":"uint8","name":"__decimals","type":"uint8"}],"name":"setTokenInfo","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
608060405234801561001057600080fd5b506000805460ff19169055615ffe806200002b6000396000f3fe608060405234801561001057600080fd5b50600436106102a95760003560e01c8063046f7da2146102ae57806306fdde03146102b8578063095ea7b3146102d657806318160ddd146102f95780631a813a3c1461030f5780631ab81cba146103175780631d55fde41461032a57806323b872dd1461033f578063240359bc14610352578063313ce567146103885780633299a4181461039d57806338dee1d3146103b057806339509351146103c35780633ca3bca3146103d65780633fd2c16a146103e957806341c262c5146103fc578063473764731461040f57806348c696c0146104225780634fe28e3a1461042b5780635c975abb1461043e5780635e442a9b146104495780635f3f2cac1461046957806361f9c3da1461047c57806363ca402d1461048f5780636a92b586146104a257806370a08231146104cd57806373ece435146104e057806377c96574146104f35780638456cb591461051b57806386651203146105235780638ab476bf1461053657806395d89b41146105495780639e0c970414610551578063a1e206c714610564578063a457c2d714610577578063a9042441146102f9578063a9059cbb1461058a578063b09f53201461059d578063b20feaaf146105a6578063b31207f2146105ec578063b6b55f25146105ff578063cdd8f59814610612578063ced72f8714610625578063d381787a1461063b578063d5002f2e1461064e578063db006a7514610656578063dbd5edc714610669578063dd62ed3e14610672578063df197956146106ab578063df6c39fb146106c0578063e1006107146106d3578063e40b9255146106e6578063ec70d800146106ef578063f0f4426014610702578063f144719514610715578063f339a70d14610735578063f5eb42dc14610748578063f7eba4201461075b578063fa597e071461076e575b600080fd5b6102b6610776565b005b6102c0610827565b6040516102cd9190615432565b60405180910390f35b6102e96102e436600461549c565b6108b9565b60405190151581526020016102cd565b6103016108cf565b6040519081526020016102cd565b6102b66108df565b6102b66103253660046154c8565b6109b1565b610332610b0c565b6040516102cd91906154e5565b6102e961034d366004615529565b610cfc565b61037b61036036600461556a565b6000908152601b60205260409020546001600160a01b031690565b6040516102cd9190615583565b60215460405160ff90911681526020016102cd565b6102b66103ab366004615639565b610da4565b6102b66103be3660046156b6565b610f06565b6102e96103d136600461549c565b6110b6565b6102b66103e43660046156dd565b6110ed565b60115461037b906001600160a01b031681565b6102b661040a3660046157db565b611596565b6102b661041d3660046154c8565b611861565b61030160075481565b61037b610439366004615856565b611977565b60005460ff166102e9565b6103016104573660046154c8565b60096020526000908152604090205481565b6102b6610477366004615884565b611e1f565b6102b661048a3660046158a1565b611f49565b61030161049d36600461556a565b6120cc565b601a546104b5906001600160801b031681565b6040516001600160801b0390911681526020016102cd565b6103016104db3660046154c8565b612112565b6102b66104ee3660046158c3565b612126565b6105066105013660046154c8565b612330565b604080519283526020830191909152016102cd565b6102b66123b5565b6102b661053136600461556a565b61245a565b6102b66105443660046154c8565b612547565b6102c061267a565b6102b661055f3660046158a1565b612689565b600f5461037b906001600160a01b031681565b6102e961058536600461549c565b6129c2565b6102e961059836600461549c565b612a4f565b61030160065481565b6105ae612a5c565b6040516102cd9190815161ffff9081168252602080840151821690830152604080840151821690830152606092830151169181019190915260800190565b6103016105fa36600461556a565b612aa9565b61030161060d36600461556a565b612ad2565b6102b66106203660046154c8565b612c11565b601e5460405161ffff90911681526020016102cd565b6102b66106493660046154c8565b612d0a565b6103016131e6565b6102b661066436600461556a565b6131f1565b610301600c5481565b610301610680366004615903565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6106b36133ca565b6040516102cd919061593c565b6102b66106ce3660046158a1565b613520565b6102b66106e136600461556a565b61375f565b61030160055481565b60175461037b906001600160a01b031681565b6102b66107103660046154c8565b61389c565b6103016107233660046154c8565b60086020526000908152604090205481565b6102b66107433660046154c8565b6139c4565b6103016107563660046154c8565b613a6a565b6102b66107693660046154c8565b613a75565b6102b6613b8b565b600f54604051633bfc46cb60e21b8152600080516020615f89833981519152916001600160a01b03169063eff11b2c906107b6908490339060040161597d565b602060405180830381865afa1580156107d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f79190615994565b61081c5760405162461bcd60e51b8152600401610813906159b6565b60405180910390fd5b610824613c56565b50565b6060601f8054610836906159e2565b80601f0160208091040260200160405190810160405280929190818152602001828054610862906159e2565b80156108af5780601f10610884576101008083540402835291602001916108af565b820191906000526020600020905b81548152906001019060200180831161089257829003601f168201915b5050505050905090565b60006108c6338484613ce3565b50600192915050565b60006108da60055490565b905090565b60005460ff16156109025760405162461bcd60e51b815260040161081390615a16565b601954604051630f41a04d60e11b81526000916001600160a01b031690631e83409a90610933903390600401615583565b6020604051808303816000875af1158015610952573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109769190615a40565b60405181815290915033907fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a9060200160405180910390a250565b600f54604051633bfc46cb60e21b8152600080516020615f49833981519152916001600160a01b03169063eff11b2c906109f1908490339060040161597d565b602060405180830381865afa158015610a0e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a329190615994565b610a4e5760405162461bcd60e51b8152600401610813906159b6565b6001600160a01b0382166000908152601d602052604090205460ff16610ab05760405162461bcd60e51b815260206004820152601760248201527613125113ce8813115111d15497d393d517d4105554d151604a1b6044820152606401610813565b6001600160a01b0382166000908152601d602052604090819020805460ff19169055517f8c097d4c8d964b147a04f3a822a31e3aa5a9104dc7db3dde0166a248b8f106c590610b00908490615583565b60405180910390a15050565b600a54600b54606091600091610b229190615a6f565b6001600160401b03811115610b3957610b39615597565b604051908082528060200260200182016040528015610b62578160200160208202803683370190505b50905060005b600b54811015610c2657600b8181548110610b8557610b85615a87565b600091825260209182902001546040805163118d75f960e11b815290516001600160a01b039092169263231aebf2926004808401938290030181865afa158015610bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf79190615a40565b828281518110610c0957610c09615a87565b602090810291909101015280610c1e81615a9d565b915050610b68565b5060005b600a54811015610cf657600a8181548110610c4757610c47615a87565b600091825260209182902001546040805163118d75f960e11b815290516001600160a01b039092169263231aebf2926004808401938290030181865afa158015610c95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb99190615a40565b600b548390610cc9908490615a6f565b81518110610cd957610cd9615a87565b602090810291909101015280610cee81615a9d565b915050610c2a565b50919050565b6001600160a01b038316600090815260026020908152604080832033845290915281205482811015610d7a5760405162461bcd60e51b815260206004820152602160248201527f5452414e534645525f414d4f554e545f455843454544535f414c4c4f57414e436044820152604560f81b6064820152608401610813565b610d85858585613e09565b610d998533610d948685615ab6565b613ce3565b506001949350505050565b6000835111610de85760405162461bcd60e51b815260206004820152601060248201526f4c49444f3a20454d5054595f4e414d4560801b6044820152606401610813565b6000825111610e2e5760405162461bcd60e51b815260206004820152601260248201527113125113ce88115354151657d4d6535093d360721b6044820152606401610813565b60008160ff1611610e775760405162461bcd60e51b81526020600482015260136024820152724c49444f3a205a45524f5f444543494d414c5360681b6044820152606401610813565b601f8054610e84906159e2565b159050610ec75760405162461bcd60e51b815260206004820152601160248201527013125113ce881390535157d4d155151151607a1b6044820152606401610813565b8251610eda90601f906020860190615376565b508151610eed9060209081850190615376565b506021805460ff191660ff929092169190911790555050565b600f54604051633bfc46cb60e21b81527f2c204f3ef59cc164f843cf6919920470e37721ba425db7893d02e60cfd0bafdc916001600160a01b03169063eff11b2c90610f58908490339060040161597d565b602060405180830381865afa158015610f75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f999190615994565b610fb55760405162461bcd60e51b8152600401610813906159b6565b6000610fc46020840184615acd565b61ffff16116110215760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a204241445f4d41585f56414c494441544f52535f5045525f4c454460448201526223a2a960e91b6064820152608401610813565b60008260600135116110755760405162461bcd60e51b815260206004820152601e60248201527f4c49444f3a204241445f4d41585f554e4c4f434b494e475f4348554e4b5300006044820152606401610813565b8160126110828282615aea565b506110b290506110986040840160208501615884565b6110a86060850160408601615884565b8460600135613e62565b5050565b3360008181526002602090815260408083206001600160a01b038716845290915281205490916108c6918590610d94908690615a6f565b600454610100900460ff1680611106575060045460ff16155b6111695760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610813565b600454610100900460ff1615801561118b576004805461ffff19166101011790555b600083116111cc5760405162461bcd60e51b815260206004820152600e60248201526d04c49444f3a205a45524f5f4341560941b6044820152606401610813565b6001600160a01b0389166112215760405162461bcd60e51b815260206004820152601c60248201527b4c49444f3a20494e434f52524543545f564b534d5f4144445245535360201b6044820152606401610813565b6001600160a01b0385166112855760405162461bcd60e51b815260206004820152602560248201527f4c49444f3a20494e434f52524543545f4f5241434c455f4d41535445525f4144604482015264445245535360d81b6064820152608401610813565b6001600160a01b0384166112e65760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f5749544844524157414c5f4144445245604482015261535360f01b6064820152608401610813565b6001600160a01b038a166113485760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a20494e434f52524543545f415554484d414e414745525f4144445260448201526245535360e81b6064820152608401610813565b6001600160a01b0388166113a95760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f434f4e54524f4c4c45525f4144445245604482015261535360f01b6064820152608401610813565b600d80546001600160a01b03808c166001600160a01b031992831617909255600e80548b8416908316179055600f8054928d1692909116919091179055600c83905560c86010556113f86153f6565b61032061140760c86000615b77565b6114119190615b77565b61ffff168082526000602083015260c86040808401919091526103206060840152601e805465ffffffffffff1916909217601960231b1761ffff60301b1916601960351b17909155601680546001600160a01b03199081166001600160a01b038b8116919091179092556015805482168c84161790556011805490911691891691821790559051637d774e3160e01b8152637d774e31906114b6903090600401615583565b600060405180830381600087803b1580156114d057600080fd5b505af11580156114e4573d6000803e3d6000fd5b5050601980546001600160a01b0319166001600160a01b03891690811790915560405163015cda1760e41b81529092506315cda1709150611529903090600401615583565b600060405180830381600087803b15801561154357600080fd5b505af1158015611557573d6000803e3d6000fd5b5050601a80546001600160801b0319166001600160801b03871617905550508115905061158a576004805461ff00191690555b50505050505050505050565b600f54604051633bfc46cb60e21b81527fdefdc47e8c8311059971baa7eda778fd22d6ea93a75a917e77534b8ce74fe4f9916001600160a01b03169063eff11b2c906115e8908490339060040161597d565b602060405180830381865afa158015611605573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116299190615994565b6116455760405162461bcd60e51b8152600401610813906159b6565b83821461168c5760405162461bcd60e51b815260206004820152601560248201527413125113ce88125390d3d4949150d517d253941555605a1b6044820152606401610813565b60005b84811015611859576000601b818888858181106116ae576116ae615a87565b60209081029290920135835250810191909152604001600020546001600160a01b03160361171c5760405162461bcd60e51b815260206004820152601b60248201527a13125113ce88155392d393d5d397d4d51054d217d050d0d3d55395602a1b6044820152606401610813565b60125461ffff1684848381811061173557611735615a87565b90506020028101906117479190615b9d565b905011156117975760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a2056414c494441544f52535f414d4f554e545f544f4f5f424947006044820152606401610813565b601b60008787848181106117ad576117ad615a87565b60209081029290920135835250810191909152604001600020546001600160a01b031663f5330e968585848181106117e7576117e7615a87565b90506020028101906117f99190615b9d565b6040518363ffffffff1660e01b8152600401611816929190615be6565b600060405180830381600087803b15801561183057600080fd5b505af1158015611844573d6000803e3d6000fd5b505050508061185290615a9d565b905061168f565b505050505050565b600f54604051633bfc46cb60e21b8152600080516020615f69833981519152916001600160a01b03169063eff11b2c906118a1908490339060040161597d565b602060405180830381865afa1580156118be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e29190615994565b6118fe5760405162461bcd60e51b8152600401610813906159b6565b6001600160a01b0382166119545760405162461bcd60e51b815260206004820152601e60248201527f4c49444f3a20494e434f52524543545f424541434f4e5f4144445245535300006044820152606401610813565b50601780546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604051633bfc46cb60e21b8152600091600080516020615f49833981519152916001600160a01b039091169063eff11b2c906119bc908490339060040161597d565b602060405180830381865afa1580156119d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fd9190615994565b611a195760405162461bcd60e51b8152600401610813906159b6565b6017546001600160a01b0316611a715760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a20554e5350454349464945445f4c45444745525f424541434f4e006044820152606401610813565b6018546001600160a01b0316611ac95760405162461bcd60e51b815260206004820181905260248201527f4c49444f3a20554e5350454349464945445f4c45444745525f464143544f52596044820152606401610813565b6011546001600160a01b0316611b1a5760405162461bcd60e51b81526020600482015260166024820152752624a2279d102727afa7a920a1a622afa6a0a9aa22a960511b6044820152606401610813565b601054600a54600b54611b2d9190615a6f565b10611b755760405162461bcd60e51b815260206004820152601860248201527713125113ce8813115111d15494d7d413d3d317d31253525560421b6044820152606401610813565b6000858152601b60205260409020546001600160a01b031615611bd75760405162461bcd60e51b815260206004820152601a6024820152794c49444f3a2053544153485f414c52454144595f45584953545360301b6044820152606401610813565b601854600d54600e5460125460135460145460405163776aecef60e11b8152600481018c9052602481018b90526001600160a01b0395861660448201529385166064850152620100009092046001600160801b0390811660848501521660a483015260c4820152600092919091169063eed5d9de9060e4016020604051808303816000875af1158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c929190615c22565b600b805460018181019092557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b038085166001600160a01b0319928316811790935560008b8152601b6020908152604080832080549095168617909455938152601c90935291819020805460ff191690931790925560115491516327c13a6b60e21b81529293501690639f04e9ac90611d39908490600401615583565b600060405180830381600087803b158015611d5357600080fd5b505af1158015611d67573d6000803e3d6000fd5b5050600e54604051639632acf760e01b815261ffff88166004820152602481018a90526001600160a01b0385811660448301529091169250639632acf79150606401600060405180830381600087803b158015611dc357600080fd5b505af1158015611dd7573d6000803e3d6000fd5b505050507f4522989a180263bb7fbc1471718de7bdd69a5d36b5d29511958afa11d2e9da04818787604051611e0e93929190615c3f565b60405180910390a195945050505050565b600f54604051633bfc46cb60e21b8152600080516020615f69833981519152916001600160a01b03169063eff11b2c90611e5f908490339060040161597d565b602060405180830381865afa158015611e7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea09190615994565b611ebc5760405162461bcd60e51b8152600401610813906159b6565b6000826001600160801b031611611f265760405162461bcd60e51b815260206004820152602860248201527f4c49444f3a20494e434f52524543545f4d41585f414c4c4f5741424c455f444960448201526746464552454e434560c01b6064820152608401610813565b50601a80546001600160801b0319166001600160801b0392909216919091179055565b336000908152601c602052604090205460ff16611f785760405162461bcd60e51b815260040161081390615c60565b8015612027578060056000828254611f909190615a6f565b925050819055508060066000828254611fa99190615a6f565b9091555050600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90611fe290339030908690600401615c8f565b6020604051808303816000875af1158015612001573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120259190615994565b505b3360009081526009602052604081208054849290612046908490615ab6565b9091555050600d546019546040516323b872dd60e01b81526001600160a01b03928316926323b872dd92612084923392909116908790600401615c8f565b6020604051808303816000875af11580156120a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c79190615994565b505050565b6000806120d860035490565b90506003546000036120ed5750600092915050565b806120f760055490565b6121019085615cb3565b61210b9190615ce8565b9392505050565b600061212061049d83613fad565b92915050565b600f54604051633bfc46cb60e21b81527f0fc26914248bb9568b0afb008dd993637f6fb6bdc9598c222c68a21e90ca53c1916001600160a01b03169063eff11b2c90612178908490339060040161597d565b602060405180830381865afa158015612195573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b99190615994565b6121d55760405162461bcd60e51b8152600401610813906159b6565b6121dd6153f6565b826121e88686615b77565b6121f29190615b77565b61ffff168082526127101080159061221c575060008461ffff16118061221c575060008361ffff16115b801561222d57506127108561ffff16105b6122715760405162461bcd60e51b815260206004820152601560248201527404c49444f3a204645455f444f4e545f4144445f555605c1b6044820152606401610813565b80516040805161ffff92831681528783166020820152868316818301529185166060830152517fb01998f6d1382c5b6c7a4b477769ce2ffbbb91adc291994665b24def9a47e4509181900360800190a161ffff9283166040820181905294831660208201819052938316606082018190529051601e80549190941663ffffffff1990911617620100009094029390931763ffffffff60201b1916600160201b90940261ffff60301b191693909317600160301b90920291909117905550565b601954604051630aff799160e41b81526000918291829182916001600160a01b039091169063aff7991090612369908890600401615583565b6040805180830381865afa158015612385573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123a99190615cfc565b90969095509350505050565b600f54604051633bfc46cb60e21b8152600080516020615f89833981519152916001600160a01b03169063eff11b2c906123f5908490339060040161597d565b602060405180830381865afa158015612412573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124369190615994565b6124525760405162461bcd60e51b8152600401610813906159b6565b610824613fc8565b600f54604051633bfc46cb60e21b8152600080516020615f89833981519152916001600160a01b03169063eff11b2c9061249a908490339060040161597d565b602060405180830381865afa1580156124b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124db9190615994565b6124f75760405162461bcd60e51b8152600401610813906159b6565b600082116125415760405162461bcd60e51b815260206004820152601760248201527604c49444f3a20494e434f52524543545f4e45575f43415604c1b6044820152606401610813565b50600c55565b600f54604051633bfc46cb60e21b81527fbd1ecc6a842ff1f2601eedd75a87543c45753bbba85c665c9f8870558fb3a2cf916001600160a01b03169063eff11b2c90612599908490339060040161597d565b602060405180830381865afa1580156125b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125da9190615994565b6125f65760405162461bcd60e51b8152600401610813906159b6565b6001600160a01b0382166126575760405162461bcd60e51b815260206004820152602260248201527f4c49444f3a20494e434f52524543545f444556454c4f504552535f4144445245604482015261535360f01b6064820152608401610813565b50601580546001600160a01b0319166001600160a01b0392909216919091179055565b606060208054610836906159e2565b336000908152601c602052604090205460ff166126b85760405162461bcd60e51b815260040161081390615c60565b601954604080516301b7603360e11b815290516000926001600160a01b03169163036ec0669160048083019260209291908290030181865afa158015612702573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127269190615a40565b90506000601960009054906101000a90046001600160a01b03166001600160a01b0316633dbfe6cb6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561277d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127a19190615a40565b600d546019546040516370a0823160e01b81529293506000926001600160a01b03928316926370a08231926127db92911690600401615583565b602060405180830381865afa1580156127f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061281c9190615a40565b905060008161282b8486615a6f565b11156128485761283b8383615ab6565b6128459085615ab6565b90505b6000816005546128589190615a6f565b6005546128659089615cb3565b61286f9190615ce8565b905080600560008282546128839190615ab6565b90915550600090506128958289615ab6565b1115612907576019546001600160a01b0316634f5b636c6128b6838a615ab6565b6040518263ffffffff1660e01b81526004016128d491815260200190565b600060405180830381600087803b1580156128ee57600080fd5b505af1158015612902573d6000803e3d6000fd5b505050505b336000908152600860205260409020548111156129335733600090815260086020526040902054612935565b805b3360009081526008602052604081208054909190612954908490615ab6565b90915550503360009081526009602052604081208054899290612978908490615ab6565b90915550506040517f28457ba4ae46aeb68ba5c1a1c15506fb3212bfff27da04dee70b81023a9ebc04906129b19033908a908a90615c3f565b60405180910390a150505050505050565b3360009081526002602090815260408083206001600160a01b038616845290915281205482811015612a365760405162461bcd60e51b815260206004820152601e60248201527f4445435245415345445f414c4c4f57414e43455f42454c4f575f5a45524f00006044820152606401610813565b612a453385610d948685615ab6565b5060019392505050565b60006108c6338484613e09565b612a646153f6565b5060408051608081018252601e5461ffff808216835262010000820481166020840152600160201b8204811693830193909352600160301b9004909116606082015290565b600080612ab560055490565b905080600003612ac85750600092915050565b806120f760035490565b6000805460ff1615612af65760405162461bcd60e51b815260040161081390615a16565b600c5482600554612b079190615a6f565b10612b505760405162461bcd60e51b815260206004820152601960248201527804c49444f3a204445504f534954535f4558434545445f43415603c1b6044820152606401610813565b600d546040516323b872dd60e01b81526001600160a01b03909116906323b872dd90612b8490339030908790600401615c8f565b6020604051808303816000875af1158015612ba3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc79190615994565b506000612bd383614020565b60405184815290915033907f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c49060200160405180910390a292915050565b600f54604051633bfc46cb60e21b8152600080516020615f49833981519152916001600160a01b03169063eff11b2c90612c51908490339060040161597d565b602060405180830381865afa158015612c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c929190615994565b612cae5760405162461bcd60e51b8152600401610813906159b6565b612cb7826140c5565b6001600160a01b0382166000908152601d602052604090819020805460ff19166001179055517fe5526d35f0db491e3e7690717b21c8148a1b5eef07240279db75404df228a59390610b00908490615583565b600f54604051633bfc46cb60e21b8152600080516020615f49833981519152916001600160a01b03169063eff11b2c90612d4a908490339060040161597d565b602060405180830381865afa158015612d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8b9190615994565b612da75760405162461bcd60e51b8152600401610813906159b6565b6001600160a01b0382166000908152601c602052604090205460ff16612ddf5760405162461bcd60e51b815260040161081390615d20565b6001600160a01b03821660009081526008602052604090205415612e455760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a204c45444745525f4841535f4e4f4e5f5a45524f5f5354414b45006044820152606401610813565b6000612e508361428e565b90506000198103612e9f5760405162461bcd60e51b815260206004820152601960248201527813125113ce8813115111d15497d393d517d11254d050931151603a1b6044820152606401610813565b6000839050806001600160a01b031663681fe70c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f069190615994565b612f4e5760405162461bcd60e51b81526020600482015260196024820152784c49444f3a204c45444745525f49535f4e4f545f454d50545960381b6044820152606401610813565b600a805460009190612f6290600190615ab6565b81548110612f7257612f72615a87565b600091825260209091200154600a80546001600160a01b039092169250829185908110612fa157612fa1615a87565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a805480612fe057612fe0615d50565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038781168352601c82526040808420805460ff19169055805163118d75f960e11b81529051601b94939287169263231aebf292600480820193918290030181865afa158015613060573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130849190615a40565b81526020808201929092526040908101600090812080546001600160a01b03191690556001600160a01b0388168152601d90925290205460ff16156130e4576001600160a01b0385166000908152601d60205260409020805460ff191690555b6011546040516369c0bc3d60e11b81526001600160a01b039091169063d381787a90613114908890600401615583565b600060405180830381600087803b15801561312e57600080fd5b505af1158015613142573d6000803e3d6000fd5b5050600e5460405163aac271ed60e01b81526001600160a01b03909116925063aac271ed9150613176908890600401615583565b600060405180830381600087803b15801561319057600080fd5b505af11580156131a4573d6000803e3d6000fd5b505050507fd80173368774864e15485d9749961d73c4199e9ef55d044c8ad3427a15ee1517856040516131d79190615583565b60405180910390a15050505050565b60006108da60035490565b60005460ff16156132145760405162461bcd60e51b815260040161081390615a16565b600061321f82612aa9565b9050600081116132685760405162461bcd60e51b81526020600482015260146024820152734c49444f3a20414d4f554e545f544f4f5f4c4f5760601b6044820152606401610813565b61327133613fad565b8111156132cc5760405162461bcd60e51b815260206004820152602360248201527f4c49444f3a2052454445454d5f414d4f554e545f455843454544535f42414c416044820152624e434560e81b6064820152608401610813565b6132d633826142f3565b5081600560008282546132e99190615ab6565b9250508190555081600760008282546133029190615a6f565b90915550506019546040516301e9a69560e41b81526001600160a01b0390911690631e9a6950906133399033908690600401615d66565b600060405180830381600087803b15801561335357600080fd5b505af1158015613367573d6000803e3d6000fd5b505060405184815260009250339150600080516020615fa98339815191529060200160405180910390a360405182815233907f4896181ff8f4543cc00db9fe9b6fb7e6f032b7eb772c72ab1ec1b4d2e03b93699060200160405180910390a25050565b600a54600b546060916000916133e09190615a6f565b6001600160401b038111156133f7576133f7615597565b604051908082528060200260200182016040528015613420578160200160208202803683370190505b50905060005b600b5481101561349d57600b818154811061344357613443615a87565b9060005260206000200160009054906101000a90046001600160a01b031682828151811061347357613473615a87565b6001600160a01b03909216602092830291909101909101528061349581615a9d565b915050613426565b5060005b600a54811015610cf657600a81815481106134be576134be615a87565b600091825260209091200154600b546001600160a01b039091169083906134e6908490615a6f565b815181106134f6576134f6615a87565b6001600160a01b03909216602092830291909101909101528061351881615a9d565b9150506134a1565b336000908152601c602052604090205460ff1661354f5760405162461bcd60e51b815260040161081390615c60565b60408051608081018252601e5461ffff808216835262010000820481166020840152600160201b82048116938301849052600160301b9091041660608201819052909160009161359e91615b77565b61ffff169050600081116135b4576135b4615d7f565b83600560008282546135c69190615a6f565b909155505033600090815260086020526040812080548692906135ea908490615a6f565b9091555050336000908152600960205260408120805486929061360e908490615a6f565b9091555050602082015160009061362790612710615d95565b61ffff166136358387615cb3565b61363f9190615ce8565b905060008161364d60055490565b6136579190615ab6565b9050600061366460055490565b9050811561368d578161367660035490565b6136809085615cb3565b61368a9190615ce8565b90505b6016546136a3906001600160a01b031682614419565b50600084866040015161ffff16836136bb9190615cb3565b6136c59190615ce8565b6016546015549192506136e5916001600160a01b039182169116836144ef565b6015546136fb906001600160a01b031682614682565b60165461371a906001600160a01b03166137158385615ab6565b614682565b7f61953b03ced70bb23c53b5a7058e431e3db88cf84a72660faea0849b785c43bd33898960405161374d93929190615c3f565b60405180910390a15050505050505050565b336000908152601c602052604090205460ff1661378e5760405162461bcd60e51b815260040161081390615c60565b336000908152600860209081526040808320546009909252909120546137b5908390615a6f565b11156138035760405162461bcd60e51b815260206004820152601d60248201527f4c49444f3a204c45444745525f4e4f545f454e4f5547485f5354414b450000006044820152606401610813565b3360009081526009602052604081208054839290613822908490615a6f565b9091555050600d5460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb906138599033908590600401615d66565b6020604051808303816000875af1158015613878573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b29190615994565b600f54604051633bfc46cb60e21b81527fe6f5d3a94b3b2e5137a1b6bff43c8dde49b099cd4958238240e4ab304e4a2b68916001600160a01b03169063eff11b2c906138ee908490339060040161597d565b602060405180830381865afa15801561390b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392f9190615994565b61394b5760405162461bcd60e51b8152600401610813906159b6565b6001600160a01b0382166139a15760405162461bcd60e51b815260206004820181905260248201527f4c49444f3a20494e434f52524543545f54524541535552595f414444524553536044820152606401610813565b50601680546001600160a01b0319166001600160a01b0392909216919091179055565b600f54604051633bfc46cb60e21b8152600080516020615f49833981519152916001600160a01b03169063eff11b2c90613a04908490339060040161597d565b602060405180830381865afa158015613a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a459190615994565b613a615760405162461bcd60e51b8152600401610813906159b6565b6110b2826140c5565b600061212082613fad565b600f54604051633bfc46cb60e21b8152600080516020615f69833981519152916001600160a01b03169063eff11b2c90613ab5908490339060040161597d565b602060405180830381865afa158015613ad2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af69190615994565b613b125760405162461bcd60e51b8152600401610813906159b6565b6001600160a01b038216613b685760405162461bcd60e51b815260206004820152601f60248201527f4c49444f3a20494e434f52524543545f464143544f52595f41444452455353006044820152606401610813565b50601880546001600160a01b0319166001600160a01b0392909216919091179055565b6011546001600160a01b03163314613be45760405162461bcd60e51b815260206004820152601c60248201527b2624a2279d102727aa2fa32927a6afa7a920a1a622afa6a0a9aa22a960211b6044820152606401610813565b601960009054906101000a90046001600160a01b03166001600160a01b0316637b2077276040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613c3457600080fd5b505af1158015613c48573d6000803e3d6000fd5b50505050613c546146bb565b565b60005460ff16613c9f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610813565b6000805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051613cd99190615583565b60405180910390a1565b60005460ff1615613d065760405162461bcd60e51b815260040161081390615a16565b6001600160a01b038316613d585760405162461bcd60e51b8152602060048201526019602482015278415050524f56455f46524f4d5f5a45524f5f4144445245535360381b6044820152606401610813565b6001600160a01b038216613da85760405162461bcd60e51b8152602060048201526017602482015276415050524f56455f544f5f5a45524f5f4144445245535360481b6044820152606401610813565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000613e1482612aa9565b9050613e218484836144ef565b826001600160a01b0316846001600160a01b0316600080516020615fa983398151915284604051613e5491815260200190565b60405180910390a350505050565b60005b600b54811015613f0457600b8181548110613e8257613e82615a87565b60009182526020909120015460405163416acf8b60e11b81526001600160a01b03909116906382d59f1690613ebf90879087908790600401615db8565b600060405180830381600087803b158015613ed957600080fd5b505af1158015613eed573d6000803e3d6000fd5b505050508080613efc90615a9d565b915050613e65565b5060005b600a54811015613fa757600a8181548110613f2557613f25615a87565b60009182526020909120015460405163416acf8b60e11b81526001600160a01b03909116906382d59f1690613f6290879087908790600401615db8565b600060405180830381600087803b158015613f7c57600080fd5b505af1158015613f90573d6000803e3d6000fd5b505050508080613f9f90615a9d565b915050613f08565b50505050565b6001600160a01b031660009081526001602052604090205490565b60005460ff1615613feb5760405162461bcd60e51b815260040161081390615a16565b6000805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613ccc3390565b6000338282036140675760405162461bcd60e51b815260206004820152601260248201527113125113ce8816915493d7d1115413d4d25560721b6044820152606401610813565b600061407284612aa9565b90508060000361407f5750825b83600560008282546140919190615a6f565b9250508190555083600660008282546140aa9190615a6f565b909155506140ba90508282614419565b5061210b8282614682565b6001600160a01b0381166000908152601c602052604090205460ff166140fd5760405162461bcd60e51b815260040161081390615d20565b600061410882614822565b905060001981036141565760405162461bcd60e51b815260206004820152601860248201527713125113ce8813115111d15497d393d517d153905093115160421b6044820152606401610813565b600b80546000919061416a90600190615ab6565b8154811061417a5761417a615a87565b600091825260209091200154600b80546001600160a01b0390921692508291849081106141a9576141a9615a87565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b8054806141e8576141e8615d50565b600082815260208120600019908301810180546001600160a01b03199081169091559201909255600a805460018101825592527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910180549091166001600160a01b0385161790556040517f85accaad76657cef23e292273789ae7a13d87db42feff1d70d4056c20d78d07190614281908590615583565b60405180910390a1505050565b6000805b600a548110156142e957826001600160a01b0316600a82815481106142b9576142b9615a87565b6000918252602090912001546001600160a01b0316036142d95792915050565b6142e281615a9d565b9050614292565b5060001992915050565b6000805460ff16156143175760405162461bcd60e51b815260040161081390615a16565b6001600160a01b03831661436a5760405162461bcd60e51b815260206004820152601a6024820152794255524e5f46524f4d5f5448455f5a45524f5f4144445245535360301b6044820152606401610813565b6001600160a01b038316600090815260016020526040902054808311156143d15760405162461bcd60e51b815260206004820152601b60248201527a4255524e5f414d4f554e545f455843454544535f42414c414e434560281b6044820152606401610813565b826143db60035490565b6143e59190615ab6565b600381905591506143f68382615ab6565b6001600160a01b0390941660009081526001602052604090209390935592915050565b6000805460ff161561443d5760405162461bcd60e51b815260040161081390615a16565b6001600160a01b03831661448e5760405162461bcd60e51b81526020600482015260186024820152774d494e545f544f5f5448455f5a45524f5f4144445245535360401b6044820152606401610813565b8161449860035490565b6144a29190615a6f565b60038190556001600160a01b0384166000908152600160205260409020549091506144ce908390615a6f565b6001600160a01b039093166000908152600160205260409020929092555090565b60005460ff16156145125760405162461bcd60e51b815260040161081390615a16565b6001600160a01b0383166145685760405162461bcd60e51b815260206004820152601e60248201527f5452414e534645525f46524f4d5f5448455f5a45524f5f4144445245535300006044820152606401610813565b6001600160a01b0382166145bd5760405162461bcd60e51b815260206004820152601c60248201527b5452414e534645525f544f5f5448455f5a45524f5f4144445245535360201b6044820152606401610813565b6001600160a01b038316600090815260016020526040902054808211156146265760405162461bcd60e51b815260206004820152601f60248201527f5452414e534645525f414d4f554e545f455843454544535f42414c414e4345006044820152606401610813565b6146308282615ab6565b6001600160a01b038086166000908152600160205260408082209390935590851681522054614660908390615a6f565b6001600160a01b03909316600090815260016020526040902092909255505050565b6001600160a01b0382166000600080516020615fa98339815191526146a6846120cc565b60405190815260200160405180910390a35050565b600060065411806146ce57506000600754115b15613c5457600a54158015906146e657506000600754115b156146fa576146f660075461487d565b6007555b600060065411801561470e57506000600754115b156147da576000600754600654116147285760065461472c565b6007545b905080600660008282546147409190615ab6565b9250508190555080600760008282546147599190615ab6565b9091555050600d5460195460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92614794929116908590600401615d66565b6020604051808303816000875af11580156147b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147d79190615994565b50505b600b5415613c545760006147ef600754614a7b565b6147fa600654614a7b565b6148049190615ddc565b905080156148155761481581614ae5565b5060006006819055600755565b6000805b600b548110156142e957826001600160a01b0316600b828154811061484d5761484d615a87565b6000918252602090912001546001600160a01b03160361486d5792915050565b61487681615a9d565b9050614826565b600a546000908061489057614890615d7f565b60008060005b8381101561493a57601d6000600a83815481106148b5576148b5615a87565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661492a5760086000600a83815481106148f8576148f8615a87565b60009182526020808320909101546001600160a01b031683528201929092526040019020546149279084615a6f565b92505b61493381615a9d565b9050614896565b508160000361494c5750929392505050565b60005b83811015614a6757601d6000600a838154811061496e5761496e615a87565b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16614a5757600060086000600a84815481106149b3576149b3615a87565b60009182526020808320909101546001600160a01b031683528201929092526040018120549150846149e5838a615cb3565b6149ef9190615ce8565b90508181116149fe5780614a00565b815b9050614a0c8183615ab6565b60086000600a8681548110614a2357614a23615a87565b60009182526020808320909101546001600160a01b03168352820192909252604001902055614a528185615a6f565b935050505b614a6081615a9d565b905061494f565b50614a728186615ab6565b95945050505050565b6000600160ff1b8210614ae15760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401610813565b5090565b600b5480614af557614af5615d7f565b6000816001600160401b03811115614b0f57614b0f615597565b604051908082528060200260200182016040528015614b38578160200160208202803683370190505b5090506000826001600160401b03811115614b5557614b55615597565b604051908082528060200260200182016040528015614b7e578160200160208202803683370190505b5090506000836001600160401b03811115614b9b57614b9b615597565b604051908082528060200260200182016040528015614bc4578160200160208202803683370190505b5090506000846001600160401b03811115614be157614be1615597565b604051908082528060200260200182016040528015614c0a578160200160208202803683370190505b50905060008060008088614c1c6108cf565b614c269190615ce8565b90506000805b8a811015614dd157600b8181548110614c4757614c47615a87565b9060005260206000200160009054906101000a90046001600160a01b0316898281518110614c7757614c77615a87565b60200260200101906001600160a01b031690816001600160a01b031681525050600860008a8381518110614cad57614cad615a87565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054888281518110614ce857614ce8615a87565b602002602001018181525050600860008a8381518110614d0a57614d0a615a87565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054878281518110614d4557614d45615a87565b602002602001018181525050878181518110614d6357614d63615a87565b602002602001015183614d769190615ddc565b91506000614d84838e615e1b565b1315614d9757614d948287615ea0565b95505b818a8281518110614daa57614daa615a87565b6020908102919091010152614dbf8285615ea0565b9350614dca81615a9d565b9050614c2c565b5050508060001480614de1575082155b15614df157505050505050505050565b60016000841215614e0c5750600019614e0984615ee1565b93505b60005b89811015614f46578160000b898281518110614e2d57614e2d615a87565b60200260200101818151614e419190615e1b565b90525088516000908a9083908110614e5b57614e5b615a87565b60200260200101511315614f36576000858c8b8481518110614e7f57614e7f615a87565b6020026020010151614e919190615e1b565b614e9b9190615efd565b9050600081898481518110614eb257614eb2615a87565b6020026020010151614ec49190615ea0565b905080600860008c8681518110614edd57614edd615a87565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000208190555080898481518110614f1c57614f1c615a87565b6020908102919091010152614f318287615ea0565b955050505b614f3f81615a9d565b9050614e0f565b506000614f53848c615ddc565b90506000811315614fb85780600860008a600081518110614f7657614f76615a87565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000828254614fad9190615a6f565b909155506150969050565b60008112156150965760005b8a81108015614fd35750600082125b15615094576000888281518110614fec57614fec615a87565b60200260200101519050600081111561508357600061500a84615ee1565b8211615016578161501f565b61501f84615ee1565b905080600860008d868151811061503857615038615a87565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020600082825461506f9190615ab6565b9091555061507f90508185615ea0565b9350505b5061508d81615a9d565b9050614fc4565b505b506000805b8a8110156152e75760008982815181106150b7576150b7615a87565b60200260200101516001600160a01b031663a5baabf06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156150fc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906151209190615f2b565b6001600160801b0316600960008c858151811061513f5761513f615a87565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020546151729190615ab6565b905087828151811061518657615186615a87565b6020026020010151811180156151f257508782815181106151a9576151a9615a87565b6020026020010151600860008c85815181106151c7576151c7615a87565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054115b156152d65780600860008c858151811061520e5761520e615a87565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054116152a45787828151811061524e5761524e615a87565b6020026020010151600860008c858151811061526c5761526c615a87565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205461529f9190615ab6565b6152c9565b8782815181106152b6576152b6615a87565b6020026020010151816152c99190615ab6565b6152d39084615a6f565b92505b506152e081615a9d565b905061509b565b50801561536957600d5460195460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92615324929116908590600401615d66565b6020604051808303816000875af1158015615343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906153679190615994565b505b5050505050505050505050565b828054615382906159e2565b90600052602060002090601f0160209004810192826153a457600085556153ea565b82601f106153bd57805160ff19168380011785556153ea565b828001600101855582156153ea579182015b828111156153ea5782518255916020019190600101906153cf565b50614ae192915061541d565b60408051608081018252600080825260208201819052918101829052606081019190915290565b5b80821115614ae1576000815560010161541e565b600060208083528351808285015260005b8181101561545f57858101830151858201604001528201615443565b81811115615471576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b038116811461082457600080fd5b600080604083850312156154af57600080fd5b82356154ba81615487565b946020939093013593505050565b6000602082840312156154da57600080fd5b813561210b81615487565b6020808252825182820181905260009190848201906040850190845b8181101561551d57835183529284019291840191600101615501565b50909695505050505050565b60008060006060848603121561553e57600080fd5b833561554981615487565b9250602084013561555981615487565b929592945050506040919091013590565b60006020828403121561557c57600080fd5b5035919050565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126155be57600080fd5b81356001600160401b03808211156155d8576155d8615597565b604051601f8301601f19908116603f0116810190828211818310171561560057615600615597565b8160405283815286602085880101111561561957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561564e57600080fd5b83356001600160401b038082111561566557600080fd5b615671878388016155ad565b9450602086013591508082111561568757600080fd5b50615694868287016155ad565b925050604084013560ff811681146156ab57600080fd5b809150509250925092565b600060808284031215610cf657600080fd5b6001600160801b038116811461082457600080fd5b60008060008060008060008060006101208a8c0312156156fc57600080fd5b893561570781615487565b985060208a013561571781615487565b975060408a013561572781615487565b965060608a013561573781615487565b955060808a013561574781615487565b945060a08a013561575781615487565b935060c08a013561576781615487565b925060e08a013591506101008a013561577f816156c8565b809150509295985092959850929598565b60008083601f8401126157a257600080fd5b5081356001600160401b038111156157b957600080fd5b6020830191508360208260051b85010111156157d457600080fd5b9250929050565b600080600080604085870312156157f157600080fd5b84356001600160401b038082111561580857600080fd5b61581488838901615790565b9096509450602087013591508082111561582d57600080fd5b5061583a87828801615790565b95989497509550505050565b61ffff8116811461082457600080fd5b60008060006060848603121561586b57600080fd5b833592506020840135915060408401356156ab81615846565b60006020828403121561589657600080fd5b813561210b816156c8565b600080604083850312156158b457600080fd5b50508035926020909101359150565b6000806000606084860312156158d857600080fd5b83356158e381615846565b925060208401356158f381615846565b915060408401356156ab81615846565b6000806040838503121561591657600080fd5b823561592181615487565b9150602083013561593181615487565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561551d5783516001600160a01b031683529284019291840191600101615958565b9182526001600160a01b0316602082015260400190565b6000602082840312156159a657600080fd5b8151801515811461210b57600080fd5b60208082526012908201527113125113ce8815539055551213d49256915160721b604082015260600190565b600181811c908216806159f657607f821691505b602082108103610cf657634e487b7160e01b600052602260045260246000fd5b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b600060208284031215615a5257600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115615a8257615a82615a59565b500190565b634e487b7160e01b600052603260045260246000fd5b600060018201615aaf57615aaf615a59565b5060010190565b600082821015615ac857615ac8615a59565b500390565b600060208284031215615adf57600080fd5b813561210b81615846565b8135615af581615846565b61ffff8116905081548161ffff1982161783556020840135615b16816156c8565b6001600160901b03199190911690911760109190911b62010000600160901b0316178155600181016040830135615b4c816156c8565b81546001600160801b0319166001600160801b03919091161790556060919091013560029190910155565b600061ffff808316818516808303821115615b9457615b94615a59565b01949350505050565b6000808335601e19843603018112615bb457600080fd5b8301803591506001600160401b03821115615bce57600080fd5b6020019150600581901b36038213156157d457600080fd5b6020808252810182905260006001600160fb1b03831115615c0657600080fd5b8260051b80856040850137600092016040019182525092915050565b600060208284031215615c3457600080fd5b815161210b81615487565b6001600160a01b039390931683526020830191909152604082015260600190565b6020808252601590820152742624a2279d102727aa2fa32927a6afa622a223a2a960591b604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6000816000190483118215151615615ccd57615ccd615a59565b500290565b634e487b7160e01b600052601260045260246000fd5b600082615cf757615cf7615cd2565b500490565b60008060408385031215615d0f57600080fd5b505080516020909101519092909150565b60208082526016908201527513125113ce8813115111d15497d393d517d193d5539160521b604082015260600190565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03929092168252602082015260400190565b634e487b7160e01b600052600160045260246000fd5b600061ffff83811690831681811015615db057615db0615a59565b039392505050565b6001600160801b039384168152919092166020820152604081019190915260600190565b60008083128015600160ff1b850184121615615dfa57615dfa615a59565b6001600160ff1b0384018313811615615e1557615e15615a59565b50500390565b60006001600160ff1b0381841382841380821686840486111615615e4157615e41615a59565b600160ff1b6000871282811687830589121615615e6057615e60615a59565b60008712925087820587128484161615615e7c57615e7c615a59565b87850587128184161615615e9257615e92615a59565b505050929093029392505050565b600080821280156001600160ff1b0384900385131615615ec257615ec2615a59565b600160ff1b8390038412811615615edb57615edb615a59565b50500190565b6000600160ff1b8201615ef657615ef6615a59565b5060000390565b600082615f0c57615f0c615cd2565b600160ff1b821460001984141615615f2657615f26615a59565b500590565b600060208284031215615f3d57600080fd5b815161210b816156c856fe585c6e254ec74f8e72b5cff099811ed8721d9039f710d9a1cb67eed6c74aa8279336eb28e461adb6ba7e620f5006a6952a65a21a4db92c2edb104bf7f1c38c63d76e3374742c17bd14ffaf46cd349ec292baf7d8425512fa8fe132557a4c967bddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203131e6f31bc4cdae492e04a878e36421ccc953a601ff8b38bc254f81fcd1d8f464736f6c634300080d0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.