Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ValidatorShare
Compiler Version
v0.5.17+commit.d19bba13
Optimization Enabled:
Yes with 200 runs
Other Settings:
istanbul EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.5.17;
import {IValidatorShare} from "./IValidatorShare.sol";
import {ERC20} from "../../common/oz/token/ERC20/ERC20.sol";
import {OwnableLockable} from "../../common/mixin/OwnableLockable.sol";
import {Initializable} from "../../common/mixin/Initializable.sol";
import {IERC20Permit} from "../../common/misc/IERC20Permit.sol";
import {StakingInfo} from "./../StakingInfo.sol";
import {IStakeManager} from "../stakeManager/IStakeManager.sol";
import {EventsHub} from "./../EventsHub.sol";
import {Registry} from "../../common/Registry.sol";
import {ECVerify} from "../../common/lib/ECVerify.sol";
contract ValidatorShare is IValidatorShare, ERC20, OwnableLockable, Initializable, IERC20Permit {
struct DelegatorUnbond {
uint256 shares;
uint256 withdrawEpoch;
}
uint256 constant EXCHANGE_RATE_PRECISION = 100;
// maximum matic possible, even if rate will be 1 and all matic will be staked in one go, it will result in 10 ^ 58
// shares
uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10 ** 29;
uint256 constant MAX_COMMISION_RATE = 100;
uint256 constant REWARD_PRECISION = 10 ** 25;
/* solhint-disable var-name-mixedcase */
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
string private constant _VERSION = "1";
bytes32 private constant PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
StakingInfo public stakingLogger;
IStakeManager public stakeManager;
uint256 public validatorId;
uint256 public validatorRewards_deprecated; // Now in StakeManager
uint256 public commissionRate_deprecated; // Now in StakeManager
uint256 private lastCommissionUpdate_deprecated; // Now in StakeManager
uint256 public minAmount;
uint256 private totalStake_deprecated; // Now in StakeManager
uint256 public rewardPerShare;
uint256 public activeAmount;
bool public delegation;
uint256 public withdrawPool;
uint256 public withdrawShares;
mapping(address => uint256) amountStaked_deprecated; // deprecated, keep for foundation delegators
mapping(address => DelegatorUnbond) public unbonds;
mapping(address => uint256) public initalRewardPerShare;
mapping(address => uint256) public unbondNonces;
mapping(address => mapping(uint256 => DelegatorUnbond)) public unbonds_new;
EventsHub public eventsHub;
IERC20Permit public polToken;
// EIP712 Storage
mapping(address => uint256) internal _nonces;
bytes32 internal _CACHED_DOMAIN_SEPARATOR;
uint256 internal _CACHED_CHAIN_ID;
bytes32 internal _HASHED_NAME;
bytes32 internal _HASHED_VERSION;
bytes32 internal _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
constructor() public {
_disableInitializer();
}
function initialize(uint256 _validatorId, address _stakingLogger, address _stakeManager) external initializer {
validatorId = _validatorId;
stakingLogger = StakingInfo(_stakingLogger);
stakeManager = IStakeManager(_stakeManager);
_transferOwnership(_stakeManager);
_getOrCacheEventsHub();
_getOrCachePOLToken();
delegation = true;
_cacheDomainSeparatorV4();
}
// ERC20 functions, dynamic
function name() public view returns (string memory) {
return string(abi.encodePacked("Delegated POL #", _toHexString(validatorId)));
}
function symbol() public view returns (string memory) {
return string(abi.encodePacked("dPOL", _toHexString(validatorId)));
}
function decimals() public pure returns (uint8) {
return 18;
}
/**
* Public View Methods
*/
function version() public pure returns (string memory) {
return "2.3.0";
}
function exchangeRate() public view returns (uint256) {
uint256 totalShares = totalSupply();
uint256 precision = _getRatePrecision();
return totalShares == 0 ? precision : stakeManager.delegatedAmount(validatorId).mul(precision).div(totalShares);
}
function getTotalStake(address user) public view returns (uint256, uint256) {
uint256 shares = balanceOf(user);
uint256 rate = exchangeRate();
if (shares == 0) {
return (0, rate);
}
return (rate.mul(shares).div(_getRatePrecision()), rate);
}
function withdrawExchangeRate() public view returns (uint256) {
uint256 precision = _getRatePrecision();
if (validatorId < 8) {
// fix of potentially broken withdrawals for future unbonding
// foundation validators have no slashing enabled and thus we can return default exchange rate
// because without slashing rate will stay constant
return precision;
}
uint256 _withdrawShares = withdrawShares;
return _withdrawShares == 0 ? precision : withdrawPool.mul(precision).div(_withdrawShares);
}
function getLiquidRewards(address user) public view returns (uint256) {
return _calculateReward(user, getRewardPerShare());
}
function getRewardPerShare() public view returns (uint256) {
return _calculateRewardPerShareWithRewards(stakeManager.delegatorsReward(validatorId));
}
function getStakeAndRewards(address user) public view returns (uint256 stakeAmount, uint256 liquidRewards) {
uint256 shares = balanceOf(user);
if (shares == 0) {
return (0, 0);
}
uint256 totalShares = totalSupply();
// stakeAmount = delegatedAmount(of this validator) * shares / totalShares
uint256 delegated = stakeManager.delegatedAmount(validatorId);
stakeAmount = delegated.mul(shares).div(totalShares);
uint256 accumulatedReward = stakeManager.delegatorsReward(validatorId);
uint256 _rewardPerShare = rewardPerShare;
if (accumulatedReward != 0 && totalShares != 0) {
_rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(REWARD_PRECISION).div(totalShares));
}
uint256 _initialRewardPerShare = initalRewardPerShare[user];
if (_rewardPerShare > _initialRewardPerShare) {
liquidRewards = _rewardPerShare.sub(_initialRewardPerShare).mul(shares).div(REWARD_PRECISION);
}
}
/**
* Public Methods
*/
function restakeAndTransferFrom(address from, uint256 value) public returns (bool, uint256) {
address to = msg.sender;
uint256 amountRestaked;
// Sender's rewards are returned
_withdrawAndTransferReward(from, true);
// recipient already has POL staked with this validator? reset their rewards
if (balanceOf(to) > 0) {
uint256 liquidReward = _calculateReward(to, rewardPerShare);
if (liquidReward != 0) {
// reset initial reward
initalRewardPerShare[to] = rewardPerShare;
if (!locked) {
// restake
amountRestaked = _buyShares(liquidReward, liquidReward, to);
if (liquidReward > amountRestaked) {
// return change to the user
_payout(liquidReward - amountRestaked, to, "Insufficent rewards", true);
stakingLogger.logDelegatorClaimRewards(validatorId, to, liquidReward - amountRestaked);
}
(uint256 totalStaked,) = getTotalStake(to);
stakingLogger.logDelegatorRestaked(validatorId, to, totalStaked);
} else {
_payout(liquidReward, to, "Insufficent rewards", true);
stakingLogger.logDelegatorClaimRewards(validatorId, to, liquidReward);
}
}
}
// Call parent's transferFrom which checks allowance and transfers shares
bool success = super.transferFrom(from, to, value);
// Log the transfer event
_getOrCacheEventsHub().logSharesTransfer(validatorId, from, to, value);
return (success, amountRestaked);
}
// carefull: this function uses POL
function transferFrom(address from, address to, uint256 value) public returns (bool) {
// send rewards to sender
_withdrawAndTransferReward(to, true);
// send rewards to receiver
_withdrawAndTransferReward(from, true);
// move shares to recipient
bool success = super.transferFrom(from, to, value);
_getOrCacheEventsHub().logSharesTransfer(validatorId, from, to, value);
return success;
}
function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) {
return _buyVoucher(_amount, _minSharesToMint, false);
}
// @dev permit only available on pol token
// @dev txn fails if frontrun, use buyVoucher instead
function buyVoucherWithPermit(
uint256 _amount,
uint256 _minSharesToMint,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public returns (uint256 amountToDeposit) {
IERC20Permit _polToken = _getOrCachePOLToken();
uint256 nonceBefore = _polToken.nonces(msg.sender);
_polToken.permit(msg.sender, address(stakeManager), _amount, deadline, v, r, s);
require(_polToken.nonces(msg.sender) == nonceBefore + 1, "Invalid permit");
return _buyVoucher(_amount, _minSharesToMint, true); // invokes stakeManager to pull token from msg.sender
}
function buyVoucherPOL(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) {
return _buyVoucher(_amount, _minSharesToMint, true);
}
function _buyVoucher(
uint256 _amount,
uint256 _minSharesToMint,
bool pol
) internal returns (uint256 amountToDeposit) {
_withdrawAndTransferReward(msg.sender, pol);
amountToDeposit = _buyShares(_amount, _minSharesToMint, msg.sender);
require(
pol
? stakeManager.delegationDepositPOL(validatorId, amountToDeposit, msg.sender)
: stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender),
"deposit failed"
);
return amountToDeposit;
}
function restake() public returns (uint256, uint256) {
return _restake(msg.sender, false);
}
function restakePOL() public returns (uint256, uint256) {
return _restake(msg.sender, true);
}
function restakeAndStakePOL(uint256 _amount) public returns (uint256, uint256) {
uint256 liquidReward = _calcAndResetReward(msg.sender);
uint256 amountPlusReward = _amount.add(liquidReward);
uint256 amountToDeposit = _buyShares(amountPlusReward, amountPlusReward, msg.sender);
require(amountToDeposit == amountPlusReward, "exchange rate not 1");
(uint256 totalStaked,) = getTotalStake(msg.sender);
stakingLogger.logDelegatorRestaked(validatorId, msg.sender, totalStaked);
// transferring POL from sender, total amountToDeposit - liquidReward
require(stakeManager.delegationDepositPOL(validatorId, _amount, msg.sender), "deposit failed");
return (amountToDeposit, liquidReward);
}
function restakeAndUnstakePOL(uint256 _amount) public returns (uint256) {
(uint256 restaked,) = _restake(msg.sender, true);
_sellVoucher_new(_amount, _amount, true);
return restaked;
}
function _restake(address user, bool pol) private returns (uint256, uint256) {
uint256 liquidReward = _calcAndResetReward(user);
uint256 amountRestaked;
if (liquidReward != 0) {
amountRestaked = _buyShares(liquidReward, 0, user);
if (liquidReward > amountRestaked) {
// return change to the user
_payout(liquidReward - amountRestaked, user, "Insufficent rewards", pol);
stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidReward - amountRestaked);
}
(uint256 totalStaked,) = getTotalStake(user);
stakingLogger.logDelegatorRestaked(validatorId, user, totalStaked);
}
return (amountRestaked, liquidReward);
}
function sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) public {
__sellVoucher(claimAmount, maximumSharesToBurn, false);
}
function sellVoucherPOL(uint256 claimAmount, uint256 maximumSharesToBurn) public {
__sellVoucher(claimAmount, maximumSharesToBurn, true);
}
function __sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool pol) internal {
(uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, pol);
DelegatorUnbond memory unbond = unbonds[msg.sender];
unbond.shares = unbond.shares.add(_withdrawPoolShare);
// refresh unbond period
unbond.withdrawEpoch = stakeManager.epoch();
unbonds[msg.sender] = unbond;
StakingInfo logger = stakingLogger;
logger.logShareBurned(validatorId, msg.sender, claimAmount, shares);
logger.logStakeUpdate(validatorId);
}
function withdrawRewards() public {
_withdrawAndTransferReward(msg.sender, false);
}
function withdrawRewardsPOL() public {
_withdrawAndTransferReward(msg.sender, true);
}
function migrateOut(address user, uint256 amount) external onlyOwner {
_withdrawAndTransferReward(user, true);
(uint256 totalStaked, uint256 rate) = getTotalStake(user);
require(totalStaked >= amount, "Migrating too much");
uint256 precision = _getRatePrecision();
uint256 shares = amount.mul(precision).div(rate);
_burn(user, shares);
stakeManager.updateValidatorState(validatorId, -int256(amount));
activeAmount = activeAmount.sub(amount);
stakingLogger.logShareBurned(validatorId, user, amount, shares);
stakingLogger.logStakeUpdate(validatorId);
stakingLogger.logDelegatorUnstaked(validatorId, user, amount);
}
function migrateIn(address user, uint256 amount) external onlyOwner {
_withdrawAndTransferReward(user, true);
_buyShares(amount, 0, user);
}
function unstakeClaimTokens() public {
_unstakeClaimTokens(false);
}
function unstakeClaimTokensPOL() public {
_unstakeClaimTokens(true);
}
function _unstakeClaimTokens(bool pol) internal {
DelegatorUnbond memory unbond = unbonds[msg.sender];
uint256 amount = _unstakeClaimTokens(unbond, pol);
delete unbonds[msg.sender];
stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, amount);
}
function updateDelegation(bool _delegation) external onlyOwner {
delegation = _delegation;
}
/**
* New shares exit API
*/
function sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn) public {
_sellVoucher_new(claimAmount, maximumSharesToBurn, false);
}
function sellVoucher_newPOL(uint256 claimAmount, uint256 maximumSharesToBurn) public {
_sellVoucher_new(claimAmount, maximumSharesToBurn, true);
}
function _sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn, bool pol) public {
(uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, pol);
uint256 unbondNonce = unbondNonces[msg.sender].add(1);
DelegatorUnbond memory unbond =
DelegatorUnbond({shares: _withdrawPoolShare, withdrawEpoch: stakeManager.epoch()});
unbonds_new[msg.sender][unbondNonce] = unbond;
unbondNonces[msg.sender] = unbondNonce;
_getOrCacheEventsHub().logShareBurnedWithId(validatorId, msg.sender, claimAmount, shares, unbondNonce);
stakingLogger.logStakeUpdate(validatorId);
}
function unstakeClaimTokens_new(uint256 unbondNonce) public {
_unstakeClaimTokens_new(unbondNonce, false);
}
function unstakeClaimTokens_newPOL(uint256 unbondNonce) public {
_unstakeClaimTokens_new(unbondNonce, true);
}
function _unstakeClaimTokens_new(uint256 unbondNonce, bool pol) internal {
DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce];
uint256 amount = _unstakeClaimTokens(unbond, pol);
delete unbonds_new[msg.sender][unbondNonce];
_getOrCacheEventsHub().logDelegatorUnstakedWithId(validatorId, msg.sender, amount, unbondNonce);
}
/**
* Private Methods
*/
function _getOrCacheEventsHub() private returns (EventsHub) {
EventsHub _eventsHub = eventsHub;
if (_eventsHub == EventsHub(0x0)) {
_eventsHub = EventsHub(Registry(stakeManager.getRegistry()).contractMap(keccak256("eventsHub")));
eventsHub = _eventsHub;
}
return _eventsHub;
}
function _getOrCachePOLToken() private returns (IERC20Permit) {
IERC20Permit _polToken = polToken;
if (_polToken == IERC20Permit(0x0)) {
_polToken = IERC20Permit(Registry(stakeManager.getRegistry()).contractMap(keccak256("pol")));
require(_polToken != IERC20Permit(0x0), "unset");
polToken = _polToken;
}
return _polToken;
}
function _sellVoucher(
uint256 claimAmount,
uint256 maximumSharesToBurn,
bool pol
) private returns (uint256, uint256) {
// first get how much staked in total and compare to target unstake amount
(uint256 totalStaked, uint256 rate) = getTotalStake(msg.sender);
require(totalStaked != 0 && totalStaked >= claimAmount, "Too much requested");
// convert requested amount back to shares
uint256 precision = _getRatePrecision();
uint256 shares = claimAmount.mul(precision).div(rate);
require(shares <= maximumSharesToBurn, "too much slippage");
_withdrawAndTransferReward(msg.sender, pol);
_burn(msg.sender, shares);
stakeManager.updateValidatorState(validatorId, -int256(claimAmount));
activeAmount = activeAmount.sub(claimAmount);
uint256 _withdrawPoolShare = claimAmount.mul(precision).div(withdrawExchangeRate());
withdrawPool = withdrawPool.add(claimAmount);
withdrawShares = withdrawShares.add(_withdrawPoolShare);
return (shares, _withdrawPoolShare);
}
function _unstakeClaimTokens(DelegatorUnbond memory unbond, bool pol) private returns (uint256) {
uint256 shares = unbond.shares;
require(
unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0,
"Incomplete withdrawal period"
);
uint256 _amount = withdrawExchangeRate().mul(shares).div(_getRatePrecision());
withdrawShares = withdrawShares.sub(shares);
withdrawPool = withdrawPool.sub(_amount);
_payout(_amount, msg.sender, "Insufficent rewards", pol);
return _amount;
}
function _getRatePrecision() private view returns (uint256) {
// if foundation validator, use old precision
if (validatorId < 8) {
return EXCHANGE_RATE_PRECISION;
}
return EXCHANGE_RATE_HIGH_PRECISION;
}
function _calculateRewardPerShareWithRewards(uint256 accumulatedReward) private view returns (uint256) {
uint256 _rewardPerShare = rewardPerShare;
if (accumulatedReward != 0) {
uint256 totalShares = totalSupply();
if (totalShares != 0) {
_rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(REWARD_PRECISION).div(totalShares));
}
}
return _rewardPerShare;
}
function _calculateReward(address user, uint256 _rewardPerShare) private view returns (uint256) {
uint256 shares = balanceOf(user);
if (shares == 0) {
return 0;
}
uint256 _initialRewardPerShare = initalRewardPerShare[user];
if (_initialRewardPerShare == _rewardPerShare) {
return 0;
}
return _rewardPerShare.sub(_initialRewardPerShare).mul(shares).div(REWARD_PRECISION);
}
function _calcAndResetReward(address user) private returns (uint256) {
uint256 _rewardPerShare =
_calculateRewardPerShareWithRewards(stakeManager.withdrawDelegatorsReward(validatorId));
uint256 liquidRewards = _calculateReward(user, _rewardPerShare);
rewardPerShare = _rewardPerShare;
initalRewardPerShare[user] = _rewardPerShare;
return liquidRewards;
}
function _withdrawAndTransferReward(address user, bool pol) private returns (uint256) {
uint256 liquidRewards = _calcAndResetReward(user);
if (liquidRewards != 0) {
_payout(liquidRewards, user, "Insufficent rewards", pol);
stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidRewards);
}
return liquidRewards;
}
function _buyShares(
uint256 _amount,
uint256 _minSharesToMint,
address user
) private onlyWhenUnlocked returns (uint256) {
require(delegation, "Delegation is disabled");
uint256 rate = exchangeRate();
uint256 precision = _getRatePrecision();
uint256 shares = _amount.mul(precision).div(rate);
require(shares >= _minSharesToMint, "Too much slippage");
require(unbonds[user].shares == 0, "Ongoing exit");
_mint(user, shares);
// clamp amount of tokens in case resulted shares requires less tokens than anticipated
_amount = rate.mul(shares).div(precision);
stakeManager.updateValidatorState(validatorId, int256(_amount));
activeAmount = activeAmount.add(_amount);
StakingInfo logger = stakingLogger;
logger.logShareMinted(validatorId, user, _amount, shares);
logger.logStakeUpdate(validatorId);
return _amount;
}
function _payout(uint256 amount, address user, string memory message, bool pol) private {
require(
pol
? stakeManager.transferFundsPOL(validatorId, amount, user)
: stakeManager.transferFunds(validatorId, amount, user),
message
);
}
function transferPOL(address to, uint256 value) public returns (bool) {
_transferShares(to, value, true);
return true;
}
function transfer(address to, uint256 value) public returns (bool) {
_transferShares(to, value, false);
return true;
}
function _transferShares(address to, uint256 value, bool pol) internal {
address from = msg.sender;
// get rewards for recipient
_withdrawAndTransferReward(to, pol);
// convert rewards to shares
_withdrawAndTransferReward(from, pol);
// move shares to recipient
super._transfer(from, to, value);
_getOrCacheEventsHub().logSharesTransfer(validatorId, from, to, value);
}
// ERC20Permit
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public {
if (block.timestamp > deadline) {
revert("ERC2612ExpiredSignature");
}
bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
// @dev for existing validators, _CACHED_DOMAIN_SEPARATOR needs to be set
// by calling _cacheDomainSeparatorV4() once before this will work
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECVerify.ecrecovery(hash, v, r, s);
if (signer != owner) {
revert("ERC2612InvalidSigner");
}
_approve(owner, spender, value);
}
function nonces(address owner) public view returns (uint256) {
return _nonces[owner];
}
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _CACHED_DOMAIN_SEPARATOR;
}
function _useNonce(address owner) private returns (uint256 current) {
current = _nonces[owner];
_nonces[owner] = current + 1;
}
function _compress(uint8 v, bytes32 r, bytes32 s) private pure returns (bytes memory) {
bytes memory signature = new bytes(65);
assembly {
mstore(add(signature, 0x20), r)
mstore(add(signature, 0x40), s)
mstore8(add(signature, 0x60), v)
}
return signature;
}
// @dev leaving the original state mutability to adhere strictly to the EIP712 interface
function eip712Version() public view returns (string memory) {
return _VERSION;
}
function _chainId() public pure returns (uint256 chainId) {
assembly {
chainId := chainid()
}
}
function _cacheDomainSeparatorV4() public returns (bytes32) {
bytes32 hashedName = keccak256(bytes(name()));
bytes32 hashedVersion = keccak256(bytes(_VERSION));
_TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = _chainId();
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator();
return _CACHED_DOMAIN_SEPARATOR;
}
function _buildDomainSeparator() private view returns (bytes32) {
return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION, _chainId(), address(this)));
}
function _hashTypedDataV4(bytes32 structHash) public view returns (bytes32) {
return _toTypedDataHash(_CACHED_DOMAIN_SEPARATOR, structHash);
}
function _toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) public pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
// utils
function _toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 4;
}
bytes memory buffer = new bytes(length);
for (uint256 i = length; i > 0; --i) {
buffer[i - 1] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
return string(buffer);
}
}pragma solidity 0.5.17;
// note this contract interface is only for stakeManager use
contract IValidatorShare {
function withdrawRewards() public;
function unstakeClaimTokens() public;
function getLiquidRewards(address user) public view returns (uint256);
function owner() public view returns (address);
function restake() public returns (uint256, uint256);
function unlock() external;
function lock() external;
function updateDelegation(bool delegation) external;
function migrateOut(address user, uint256 amount) external;
function migrateIn(address user, uint256 amount) external;
}pragma solidity ^0.5.2;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* https://eips.ethereum.org/EIPS/eip-20
* Originally based on code by FirstBlood:
* https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*
* This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for
* all accounts just by listening to said events. Note that this isn't required by the specification, and other
* compliant implementations may not do it.
*/
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowed;
uint256 private _totalSupply;
/**
* @dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev Gets the balance of the specified address.
* @param owner The address to query the balance of.
* @return A uint256 representing the amount owned by the passed address.
*/
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param owner address The address which owns the funds.
* @param spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
/**
* @dev Transfer token to a specified address
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* 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
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
*/
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* Note that while this function emits an Approval event, this is not required as per the specification,
* and other compliant implementations may not emit the event.
* @param from address The address which you want to send tokens from
* @param to address The address which you want to transfer to
* @param value uint256 the amount of tokens to be transferred
*/
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
return true;
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
* Emits an Approval event.
* @param spender The address which will spend the funds.
* @param subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
return true;
}
/**
* @dev Transfer token for a specified addresses
* @param from The address to transfer from.
* @param to The address to transfer to.
* @param value The amount to be transferred.
*/
function _transfer(address from, address to, uint256 value) internal {
require(to != address(0));
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(from, to, value);
}
/**
* @dev Internal function that mints an amount of the token and assigns it to
* an account. This encapsulates the modification of balances such that the
* proper events are emitted.
* @param account The account that will receive the created tokens.
* @param value The amount that will be created.
*/
function _mint(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account.
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burn(address account, uint256 value) internal {
require(account != address(0));
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
/**
* @dev Approve an address to spend another addresses' tokens.
* @param owner The address that owns the tokens.
* @param spender The address that will spend the tokens.
* @param value The number of tokens that can be spent.
*/
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0));
require(owner != address(0));
_allowed[owner][spender] = value;
emit Approval(owner, spender, value);
}
/**
* @dev Internal function that burns an amount of the token of a given
* account, deducting from the sender's allowance for said account. Uses the
* internal burn function.
* Emits an Approval event (reflecting the reduced allowance).
* @param account The account whose tokens will be burnt.
* @param value The amount that will be burnt.
*/
function _burnFrom(address account, uint256 value) internal {
_burn(account, value);
_approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
}
}pragma solidity ^0.5.2;
import {Lockable} from "./Lockable.sol";
import {Ownable} from "../oz/ownership/Ownable.sol";
contract OwnableLockable is Lockable, Ownable {
function lock() public onlyOwner {
super.lock();
}
function unlock() public onlyOwner {
super.unlock();
}
}pragma solidity ^0.5.2;
contract Initializable {
bool internal inited = false;
modifier initializer() {
require(!inited, "already inited");
inited = true;
_;
}
function _disableInitializer() internal {
inited = true;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.5.17;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}pragma solidity ^0.5.2;
import {Registry} from "../common/Registry.sol";
import {SafeMath} from "../common/oz/math/SafeMath.sol";
import {Ownable} from "../common/oz/ownership/Ownable.sol";
// dummy interface to avoid cyclic dependency
contract IStakeManagerLocal {
enum Status {Inactive, Active, Locked, Unstaked}
struct Validator {
uint256 amount;
uint256 reward;
uint256 activationEpoch;
uint256 deactivationEpoch;
uint256 jailTime;
address signer;
address contractAddress;
Status status;
}
mapping(uint256 => Validator) public validators;
bytes32 public accountStateRoot;
uint256 public activeAmount; // delegation amount from validator contract
uint256 public validatorRewards;
function currentValidatorSetTotalStake() public view returns (uint256);
// signer to Validator mapping
function signerToValidator(address validatorAddress)
public
view
returns (uint256);
function isValidator(uint256 validatorId) public view returns (bool);
}
contract StakingInfo is Ownable {
using SafeMath for uint256;
mapping(uint256 => uint256) public validatorNonce;
/// @dev Emitted when validator stakes in '_stakeFor()' in StakeManager.
/// @param signer validator address.
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param activationEpoch validator's first epoch as proposer.
/// @param amount staking amount.
/// @param total total staking amount.
/// @param signerPubkey public key of the validator
event Staked(
address indexed signer,
uint256 indexed validatorId,
uint256 nonce,
uint256 indexed activationEpoch,
uint256 amount,
uint256 total,
bytes signerPubkey
);
/// @dev Emitted when validator unstakes in 'unstakeClaim()'
/// @param user address of the validator.
/// @param validatorId unique integer to identify a validator.
/// @param amount staking amount.
/// @param total total staking amount.
event Unstaked(
address indexed user,
uint256 indexed validatorId,
uint256 amount,
uint256 total
);
/// @dev Emitted when validator unstakes in '_unstake()'.
/// @param user address of the validator.
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param deactivationEpoch last epoch for validator.
/// @param amount staking amount.
event UnstakeInit(
address indexed user,
uint256 indexed validatorId,
uint256 nonce,
uint256 deactivationEpoch,
uint256 indexed amount
);
/// @dev Emitted when the validator public key is updated in 'updateSigner()'.
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param oldSigner old address of the validator.
/// @param newSigner new address of the validator.
/// @param signerPubkey public key of the validator.
event SignerChange(
uint256 indexed validatorId,
uint256 nonce,
address indexed oldSigner,
address indexed newSigner,
bytes signerPubkey
);
event Restaked(uint256 indexed validatorId, uint256 amount, uint256 total);
event Jailed(
uint256 indexed validatorId,
uint256 indexed exitEpoch,
address indexed signer
);
event UnJailed(uint256 indexed validatorId, address indexed signer);
event Slashed(uint256 indexed nonce, uint256 indexed amount);
event ThresholdChange(uint256 newThreshold, uint256 oldThreshold);
event DynastyValueChange(uint256 newDynasty, uint256 oldDynasty);
event ProposerBonusChange(
uint256 newProposerBonus,
uint256 oldProposerBonus
);
event RewardUpdate(uint256 newReward, uint256 oldReward);
/// @dev Emitted when validator confirms the auction bid and at the time of restaking in confirmAuctionBid() and restake().
/// @param validatorId unique integer to identify a validator.
/// @param nonce to synchronize the events in heimdal.
/// @param newAmount the updated stake amount.
event StakeUpdate(
uint256 indexed validatorId,
uint256 indexed nonce,
uint256 indexed newAmount
);
event ClaimRewards(
uint256 indexed validatorId,
uint256 indexed amount,
uint256 indexed totalAmount
);
event StartAuction(
uint256 indexed validatorId,
uint256 indexed amount,
uint256 indexed auctionAmount
);
event ConfirmAuction(
uint256 indexed newValidatorId,
uint256 indexed oldValidatorId,
uint256 indexed amount
);
event TopUpFee(address indexed user, uint256 indexed fee);
event ClaimFee(address indexed user, uint256 indexed fee);
// Delegator events
event ShareMinted(
uint256 indexed validatorId,
address indexed user,
uint256 indexed amount,
uint256 tokens
);
event ShareBurned(
uint256 indexed validatorId,
address indexed user,
uint256 indexed amount,
uint256 tokens
);
event DelegatorClaimedRewards(
uint256 indexed validatorId,
address indexed user,
uint256 indexed rewards
);
event DelegatorRestaked(
uint256 indexed validatorId,
address indexed user,
uint256 indexed totalStaked
);
event DelegatorUnstaked(
uint256 indexed validatorId,
address indexed user,
uint256 amount
);
event UpdateCommissionRate(
uint256 indexed validatorId,
uint256 indexed newCommissionRate,
uint256 indexed oldCommissionRate
);
Registry public registry;
modifier onlyValidatorContract(uint256 validatorId) {
address _contract;
(, , , , , , _contract, ) = IStakeManagerLocal(
registry.getStakeManagerAddress()
)
.validators(validatorId);
require(_contract == msg.sender,
"Invalid sender, not validator");
_;
}
modifier StakeManagerOrValidatorContract(uint256 validatorId) {
address _contract;
address _stakeManager = registry.getStakeManagerAddress();
(, , , , , , _contract, ) = IStakeManagerLocal(_stakeManager).validators(
validatorId
);
require(_contract == msg.sender || _stakeManager == msg.sender,
"Invalid sender, not stake manager or validator contract");
_;
}
modifier onlyStakeManager() {
require(registry.getStakeManagerAddress() == msg.sender,
"Invalid sender, not stake manager");
_;
}
modifier onlySlashingManager() {
require(registry.getSlashingManagerAddress() == msg.sender,
"Invalid sender, not slashing manager");
_;
}
constructor(address _registry) public {
registry = Registry(_registry);
}
function updateNonce(
uint256[] calldata validatorIds,
uint256[] calldata nonces
) external onlyOwner {
require(validatorIds.length == nonces.length, "args length mismatch");
for (uint256 i = 0; i < validatorIds.length; ++i) {
validatorNonce[validatorIds[i]] = nonces[i];
}
}
function logStaked(
address signer,
bytes memory signerPubkey,
uint256 validatorId,
uint256 activationEpoch,
uint256 amount,
uint256 total
) public onlyStakeManager {
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit Staked(
signer,
validatorId,
validatorNonce[validatorId],
activationEpoch,
amount,
total,
signerPubkey
);
}
function logUnstaked(
address user,
uint256 validatorId,
uint256 amount,
uint256 total
) public onlyStakeManager {
emit Unstaked(user, validatorId, amount, total);
}
function logUnstakeInit(
address user,
uint256 validatorId,
uint256 deactivationEpoch,
uint256 amount
) public onlyStakeManager {
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit UnstakeInit(
user,
validatorId,
validatorNonce[validatorId],
deactivationEpoch,
amount
);
}
function logSignerChange(
uint256 validatorId,
address oldSigner,
address newSigner,
bytes memory signerPubkey
) public onlyStakeManager {
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit SignerChange(
validatorId,
validatorNonce[validatorId],
oldSigner,
newSigner,
signerPubkey
);
}
function logRestaked(uint256 validatorId, uint256 amount, uint256 total)
public
onlyStakeManager
{
emit Restaked(validatorId, amount, total);
}
function logJailed(uint256 validatorId, uint256 exitEpoch, address signer)
public
onlyStakeManager
{
emit Jailed(validatorId, exitEpoch, signer);
}
function logUnjailed(uint256 validatorId, address signer)
public
onlyStakeManager
{
emit UnJailed(validatorId, signer);
}
function logSlashed(uint256 nonce, uint256 amount)
public
onlySlashingManager
{
emit Slashed(nonce, amount);
}
function logThresholdChange(uint256 newThreshold, uint256 oldThreshold)
public
onlyStakeManager
{
emit ThresholdChange(newThreshold, oldThreshold);
}
function logDynastyValueChange(uint256 newDynasty, uint256 oldDynasty)
public
onlyStakeManager
{
emit DynastyValueChange(newDynasty, oldDynasty);
}
function logProposerBonusChange(
uint256 newProposerBonus,
uint256 oldProposerBonus
) public onlyStakeManager {
emit ProposerBonusChange(newProposerBonus, oldProposerBonus);
}
function logRewardUpdate(uint256 newReward, uint256 oldReward)
public
onlyStakeManager
{
emit RewardUpdate(newReward, oldReward);
}
function logStakeUpdate(uint256 validatorId)
public
StakeManagerOrValidatorContract(validatorId)
{
validatorNonce[validatorId] = validatorNonce[validatorId].add(1);
emit StakeUpdate(
validatorId,
validatorNonce[validatorId],
totalValidatorStake(validatorId)
);
}
function logClaimRewards(
uint256 validatorId,
uint256 amount,
uint256 totalAmount
) public onlyStakeManager {
emit ClaimRewards(validatorId, amount, totalAmount);
}
function logStartAuction(
uint256 validatorId,
uint256 amount,
uint256 auctionAmount
) public onlyStakeManager {
emit StartAuction(validatorId, amount, auctionAmount);
}
function logConfirmAuction(
uint256 newValidatorId,
uint256 oldValidatorId,
uint256 amount
) public onlyStakeManager {
emit ConfirmAuction(newValidatorId, oldValidatorId, amount);
}
function logTopUpFee(address user, uint256 fee) public onlyStakeManager {
emit TopUpFee(user, fee);
}
function logClaimFee(address user, uint256 fee) public onlyStakeManager {
emit ClaimFee(user, fee);
}
function getStakerDetails(uint256 validatorId)
public
view
returns (
uint256 amount,
uint256 reward,
uint256 activationEpoch,
uint256 deactivationEpoch,
address signer,
uint256 _status
)
{
IStakeManagerLocal stakeManager = IStakeManagerLocal(
registry.getStakeManagerAddress()
);
address _contract;
IStakeManagerLocal.Status status;
(
amount,
reward,
activationEpoch,
deactivationEpoch,
,
signer,
_contract,
status
) = stakeManager.validators(validatorId);
_status = uint256(status);
if (_contract != address(0x0)) {
reward += IStakeManagerLocal(_contract).validatorRewards();
}
}
function totalValidatorStake(uint256 validatorId)
public
view
returns (uint256 validatorStake)
{
address contractAddress;
(validatorStake, , , , , , contractAddress, ) = IStakeManagerLocal(
registry.getStakeManagerAddress()
)
.validators(validatorId);
if (contractAddress != address(0x0)) {
validatorStake += IStakeManagerLocal(contractAddress).activeAmount();
}
}
function getAccountStateRoot()
public
view
returns (bytes32 accountStateRoot)
{
accountStateRoot = IStakeManagerLocal(registry.getStakeManagerAddress())
.accountStateRoot();
}
function getValidatorContractAddress(uint256 validatorId)
public
view
returns (address ValidatorContract)
{
(, , , , , , ValidatorContract, ) = IStakeManagerLocal(
registry.getStakeManagerAddress()
)
.validators(validatorId);
}
// validator Share contract logging func
function logShareMinted(
uint256 validatorId,
address user,
uint256 amount,
uint256 tokens
) public onlyValidatorContract(validatorId) {
emit ShareMinted(validatorId, user, amount, tokens);
}
function logShareBurned(
uint256 validatorId,
address user,
uint256 amount,
uint256 tokens
) public onlyValidatorContract(validatorId) {
emit ShareBurned(validatorId, user, amount, tokens);
}
function logDelegatorClaimRewards(
uint256 validatorId,
address user,
uint256 rewards
) public onlyValidatorContract(validatorId) {
emit DelegatorClaimedRewards(validatorId, user, rewards);
}
function logDelegatorRestaked(
uint256 validatorId,
address user,
uint256 totalStaked
) public onlyValidatorContract(validatorId) {
emit DelegatorRestaked(validatorId, user, totalStaked);
}
function logDelegatorUnstaked(uint256 validatorId, address user, uint256 amount)
public
onlyValidatorContract(validatorId)
{
emit DelegatorUnstaked(validatorId, user, amount);
}
// deprecated
function logUpdateCommissionRate(
uint256 validatorId,
uint256 newCommissionRate,
uint256 oldCommissionRate
) public onlyValidatorContract(validatorId) {
emit UpdateCommissionRate(
validatorId,
newCommissionRate,
oldCommissionRate
);
}
}pragma solidity 0.5.17;
contract IStakeManager {
function transferFunds(uint256 validatorId, uint256 amount, address delegator) external returns (bool);
function transferFundsPOL(uint256 validatorId, uint256 amount, address delegator) external returns (bool);
function delegationDeposit(uint256 validatorId, uint256 amount, address delegator) external returns (bool);
function delegationDepositPOL(uint256 validatorId, uint256 amount, address delegator) external returns (bool);
function unstake(uint256 validatorId) external;
function unstakePOL(uint256 validatorId) external;
function totalStakedFor(address addr) external view returns (uint256);
function stakeFor(
address user,
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes memory signerPubkey
) public;
function stakeForPOL(
address user,
uint256 amount,
uint256 heimdallFee,
bool acceptDelegation,
bytes memory signerPubkey
) public;
function checkSignatures(
uint256 blockInterval,
bytes32 voteHash,
bytes32 stateRoot,
address proposer,
uint256[3][] calldata sigs
) external returns (uint256);
function updateValidatorState(uint256 validatorId, int256 amount) public;
function ownerOf(uint256 tokenId) public view returns (address);
function validatorStake(uint256 validatorId) public view returns (uint256);
function epoch() public view returns (uint256);
function getRegistry() public view returns (address);
function withdrawalDelay() public view returns (uint256);
function delegatedAmount(uint256 validatorId) public view returns (uint256);
function decreaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) public;
function withdrawDelegatorsReward(uint256 validatorId) public returns (uint256);
function delegatorsReward(uint256 validatorId) public view returns (uint256);
}pragma solidity ^0.5.2;
import {Registry} from "../common/Registry.sol";
import {Initializable} from "../common/mixin/Initializable.sol";
contract IStakeManagerEventsHub {
struct Validator {
uint256 amount;
uint256 reward;
uint256 activationEpoch;
uint256 deactivationEpoch;
uint256 jailTime;
address signer;
address contractAddress;
}
mapping(uint256 => Validator) public validators;
}
contract EventsHub is Initializable {
Registry public registry;
modifier onlyValidatorContract(uint256 validatorId) {
address _contract;
(,,,,,, _contract) = IStakeManagerEventsHub(registry.getStakeManagerAddress()).validators(validatorId);
require(_contract == msg.sender, "not validator");
_;
}
modifier onlyStakeManager() {
require(registry.getStakeManagerAddress() == msg.sender, "Invalid sender, not stake manager");
_;
}
function initialize(Registry _registry) external initializer {
registry = _registry;
}
event ShareBurnedWithId(
uint256 indexed validatorId, address indexed user, uint256 indexed amount, uint256 tokens, uint256 nonce
);
function logShareBurnedWithId(
uint256 validatorId,
address user,
uint256 amount,
uint256 tokens,
uint256 nonce
) public onlyValidatorContract(validatorId) {
emit ShareBurnedWithId(validatorId, user, amount, tokens, nonce);
}
event DelegatorUnstakeWithId(uint256 indexed validatorId, address indexed user, uint256 amount, uint256 nonce);
function logDelegatorUnstakedWithId(
uint256 validatorId,
address user,
uint256 amount,
uint256 nonce
) public onlyValidatorContract(validatorId) {
emit DelegatorUnstakeWithId(validatorId, user, amount, nonce);
}
event RewardParams(
uint256 rewardDecreasePerCheckpoint, uint256 maxRewardedCheckpoints, uint256 checkpointRewardDelta
);
function logRewardParams(
uint256 rewardDecreasePerCheckpoint,
uint256 maxRewardedCheckpoints,
uint256 checkpointRewardDelta
) public onlyStakeManager {
emit RewardParams(rewardDecreasePerCheckpoint, maxRewardedCheckpoints, checkpointRewardDelta);
}
event UpdateCommissionRate(
uint256 indexed validatorId, uint256 indexed newCommissionRate, uint256 indexed oldCommissionRate
);
function logUpdateCommissionRate(
uint256 validatorId,
uint256 newCommissionRate,
uint256 oldCommissionRate
) public onlyStakeManager {
emit UpdateCommissionRate(validatorId, newCommissionRate, oldCommissionRate);
}
event SharesTransfer(uint256 indexed validatorId, address indexed from, address indexed to, uint256 value);
function logSharesTransfer(
uint256 validatorId,
address from,
address to,
uint256 value
) public onlyValidatorContract(validatorId) {
emit SharesTransfer(validatorId, from, to, value);
}
}pragma solidity ^0.5.2;
import {Governable} from "./governance/Governable.sol";
import {IWithdrawManager} from "../root/withdrawManager/IWithdrawManager.sol";
contract Registry is Governable {
// @todo hardcode constants
bytes32 private constant WETH_TOKEN = keccak256("wethToken");
bytes32 private constant DEPOSIT_MANAGER = keccak256("depositManager");
bytes32 private constant STAKE_MANAGER = keccak256("stakeManager");
bytes32 private constant VALIDATOR_SHARE = keccak256("validatorShare");
bytes32 private constant WITHDRAW_MANAGER = keccak256("withdrawManager");
bytes32 private constant CHILD_CHAIN = keccak256("childChain");
bytes32 private constant STATE_SENDER = keccak256("stateSender");
bytes32 private constant SLASHING_MANAGER = keccak256("slashingManager");
address public erc20Predicate;
address public erc721Predicate;
mapping(bytes32 => address) public contractMap;
mapping(address => address) public rootToChildToken;
mapping(address => address) public childToRootToken;
mapping(address => bool) public proofValidatorContracts;
mapping(address => bool) public isERC721;
enum Type {
Invalid,
ERC20,
ERC721,
Custom
}
struct Predicate {
Type _type;
}
mapping(address => Predicate) public predicates;
event TokenMapped(address indexed rootToken, address indexed childToken);
event ProofValidatorAdded(address indexed validator, address indexed from);
event ProofValidatorRemoved(address indexed validator, address indexed from);
event PredicateAdded(address indexed predicate, address indexed from);
event PredicateRemoved(address indexed predicate, address indexed from);
event ContractMapUpdated(bytes32 indexed key, address indexed previousContract, address indexed newContract);
constructor(address _governance) public Governable(_governance) {}
function updateContractMap(bytes32 _key, address _address) external onlyGovernance {
emit ContractMapUpdated(_key, contractMap[_key], _address);
contractMap[_key] = _address;
}
/**
* @dev Map root token to child token
* @param _rootToken Token address on the root chain
* @param _childToken Token address on the child chain
* @param _isERC721 Is the token being mapped ERC721
*/
function mapToken(address _rootToken, address _childToken, bool _isERC721) external onlyGovernance {
require(_rootToken != address(0x0) && _childToken != address(0x0), "INVALID_TOKEN_ADDRESS");
rootToChildToken[_rootToken] = _childToken;
childToRootToken[_childToken] = _rootToken;
isERC721[_rootToken] = _isERC721;
IWithdrawManager(contractMap[WITHDRAW_MANAGER]).createExitQueue(_rootToken);
emit TokenMapped(_rootToken, _childToken);
}
function addErc20Predicate(address predicate) public onlyGovernance {
require(predicate != address(0x0), "Can not add null address as predicate");
erc20Predicate = predicate;
addPredicate(predicate, Type.ERC20);
}
function addErc721Predicate(address predicate) public onlyGovernance {
erc721Predicate = predicate;
addPredicate(predicate, Type.ERC721);
}
function addPredicate(address predicate, Type _type) public onlyGovernance {
require(predicates[predicate]._type == Type.Invalid, "Predicate already added");
predicates[predicate]._type = _type;
emit PredicateAdded(predicate, msg.sender);
}
function removePredicate(address predicate) public onlyGovernance {
require(predicates[predicate]._type != Type.Invalid, "Predicate does not exist");
delete predicates[predicate];
emit PredicateRemoved(predicate, msg.sender);
}
function getValidatorShareAddress() public view returns (address) {
return contractMap[VALIDATOR_SHARE];
}
function getWethTokenAddress() public view returns (address) {
return contractMap[WETH_TOKEN];
}
function getDepositManagerAddress() public view returns (address) {
return contractMap[DEPOSIT_MANAGER];
}
function getStakeManagerAddress() public view returns (address) {
return contractMap[STAKE_MANAGER];
}
function getSlashingManagerAddress() public view returns (address) {
return contractMap[SLASHING_MANAGER];
}
function getWithdrawManagerAddress() public view returns (address) {
return contractMap[WITHDRAW_MANAGER];
}
function getChildChainAndStateSender() public view returns (address, address) {
return (contractMap[CHILD_CHAIN], contractMap[STATE_SENDER]);
}
function isTokenMapped(address _token) public view returns (bool) {
return rootToChildToken[_token] != address(0x0);
}
function isTokenMappedAndIsErc721(address _token) public view returns (bool) {
require(isTokenMapped(_token), "TOKEN_NOT_MAPPED");
return isERC721[_token];
}
function isTokenMappedAndGetPredicate(address _token) public view returns (address) {
if (isTokenMappedAndIsErc721(_token)) {
return erc721Predicate;
}
return erc20Predicate;
}
function isChildTokenErc721(address childToken) public view returns (bool) {
address rootToken = childToRootToken[childToken];
require(rootToken != address(0x0), "Child token is not mapped");
return isERC721[rootToken];
}
}pragma solidity ^0.5.2;
library ECVerify {
function ecrecovery(bytes32 hash, uint256[3] memory sig) internal pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(sig)
s := mload(add(sig, 32))
v := byte(31, mload(add(sig, 64)))
}
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return address(0x0);
}
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0x0);
}
// get address out of hash and signature
address result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0));
return result;
}
function ecrecovery(bytes32 hash, bytes memory sig) internal pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return address(0x0);
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := and(mload(add(sig, 65)), 255)
}
// https://github.com/ethereum/go-ethereum/issues/2053
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0x0);
}
// get address out of hash and signature
address result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0));
return result;
}
function ecrecovery(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
// get address out of hash and signature
address result = ecrecover(hash, v, r, s);
// ecrecover returns zero on error
require(result != address(0x0), "signature verification failed");
return result;
}
function ecverify(bytes32 hash, bytes memory sig, address signer) internal pure returns (bool) {
return signer == ecrecovery(hash, sig);
}
}pragma solidity ^0.5.2;
/**
* @title ERC20 interface
* @dev see https://eips.ethereum.org/EIPS/eip-20
*/
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}pragma solidity ^0.5.2;
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}pragma solidity ^0.5.2;
contract Lockable {
bool public locked;
modifier onlyWhenUnlocked() {
_assertUnlocked();
_;
}
function _assertUnlocked() private view {
require(!locked, "locked");
}
function lock() public {
locked = true;
}
function unlock() public {
locked = false;
}
}pragma solidity ^0.5.2;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() internal {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
/**
* @return the address of the owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner());
_;
}
/**
* @return true if `msg.sender` is the owner of the contract.
*/
function isOwner() public view returns (bool) {
return msg.sender == _owner;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
* @notice Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}pragma solidity ^0.5.2;
import {IGovernance} from "./IGovernance.sol";
contract Governable {
IGovernance public governance;
constructor(address _governance) public {
governance = IGovernance(_governance);
}
modifier onlyGovernance() {
_assertGovernance();
_;
}
function _assertGovernance() private view {
require(msg.sender == address(governance), "Only governance contract is authorized");
}
}pragma solidity ^0.5.2;
contract IWithdrawManager {
function createExitQueue(address token) external;
function verifyInclusion(
bytes calldata data,
uint8 offset,
bool verifyTxInclusion
) external view returns (uint256 age);
function addExitToQueue(
address exitor,
address childToken,
address rootToken,
uint256 exitAmountOrTokenId,
bytes32 txHash,
bool isRegularExit,
uint256 priority
) external;
function addInput(uint256 exitId, uint256 age, address utxoOwner, address token) external;
function challengeExit(
uint256 exitId,
uint256 inputId,
bytes calldata challengeData,
address adjudicatorPredicate
) external;
}pragma solidity ^0.5.2;
interface IGovernance {
function update(address target, bytes calldata data) external;
}{
"remappings": [
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"forge-std/=lib/forge-std/src/",
"hardhat/=node_modules/hardhat/",
"@ensdomains/=node_modules/@ensdomains/",
"openzeppelin-solidity/=node_modules/openzeppelin-solidity/",
"solidity-rlp/=node_modules/solidity-rlp/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "istanbul"
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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"},{"constant":true,"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"_cacheDomainSeparatorV4","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"_chainId","outputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"structHash","type":"bytes32"}],"name":"_hashTypedDataV4","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"maximumSharesToBurn","type":"uint256"},{"internalType":"bool","name":"pol","type":"bool"}],"name":"_sellVoucher_new","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"internalType":"bytes32","name":"structHash","type":"bytes32"}],"name":"_toTypedDataHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"activeAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minSharesToMint","type":"uint256"}],"name":"buyVoucher","outputs":[{"internalType":"uint256","name":"amountToDeposit","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minSharesToMint","type":"uint256"}],"name":"buyVoucherPOL","outputs":[{"internalType":"uint256","name":"amountToDeposit","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_minSharesToMint","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"buyVoucherWithPermit","outputs":[{"internalType":"uint256","name":"amountToDeposit","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"commissionRate_deprecated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"delegation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"eip712Version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"eventsHub","outputs":[{"internalType":"contract EventsHub","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"exchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getLiquidRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getStakeAndRewards","outputs":[{"internalType":"uint256","name":"stakeAmount","type":"uint256"},{"internalType":"uint256","name":"liquidRewards","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getTotalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"initalRewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_validatorId","type":"uint256"},{"internalType":"address","name":"_stakingLogger","type":"address"},{"internalType":"address","name":"_stakeManager","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"lock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"migrateIn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"migrateOut","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"polToken","outputs":[{"internalType":"contract IERC20Permit","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"restake","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"restakeAndStakePOL","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"restakeAndTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"restakeAndUnstakePOL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"restakePOL","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardPerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"maximumSharesToBurn","type":"uint256"}],"name":"sellVoucher","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"maximumSharesToBurn","type":"uint256"}],"name":"sellVoucherPOL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"maximumSharesToBurn","type":"uint256"}],"name":"sellVoucher_new","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"claimAmount","type":"uint256"},{"internalType":"uint256","name":"maximumSharesToBurn","type":"uint256"}],"name":"sellVoucher_newPOL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"stakeManager","outputs":[{"internalType":"contract IStakeManager","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakingLogger","outputs":[{"internalType":"contract StakingInfo","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferPOL","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unbondNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"unbonds","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"withdrawEpoch","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"unbonds_new","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"withdrawEpoch","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unstakeClaimTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unstakeClaimTokensPOL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"unbondNonce","type":"uint256"}],"name":"unstakeClaimTokens_new","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"unbondNonce","type":"uint256"}],"name":"unstakeClaimTokens_newPOL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_delegation","type":"bool"}],"name":"updateDelegation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"validatorId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorRewards_deprecated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"withdrawExchangeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"withdrawPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"withdrawRewardsPOL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"withdrawShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
60806040526003805460ff60a81b191690553480156200001e57600080fd5b5060038054610100338102610100600160a81b0319909216919091179182905560405191046001600160a01b0316906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620000886001600160e01b036200008e16565b620000a3565b6003805460ff60a81b1916600160a81b179055565b613fd080620000b36000396000f3fe608060405234801561001057600080fd5b506004361061043e5760003560e01c80637ecebe0011610236578063b60c76fa1161013b578063dd62ed3e116100c3578063e570b78b11610087578063e570b78b14610b9b578063e97fddc214610bbe578063eaf43bb514610bdb578063f2fde38b14610c19578063f83d08ba14610c3f5761043e565b8063dd62ed3e14610b14578063df5cf72314610b42578063e0db556b14610b4a578063e4457a8a14610b52578063e4cd1aec14610b755761043e565b8063c7b8981c1161010a578063c7b8981c14610a73578063c83ec04d14610a7b578063c8f1ecd814610a9e578063cf30901214610abb578063d505accf14610ac35761043e565b8063b60c76fa14610a14578063b6658d0714610a40578063b89b63c114610a48578063bfb18f2914610a6b5761043e565b80638f32d59b116101be578063a0c1ca341161018d578063a0c1ca3414610954578063a457c2d714610980578063a69df4b5146109ac578063a9059cbb146109b4578063b4988fd0146109e05761043e565b80638f32d59b1461093457806395d89b411461093c5780639ad5f5a4146109445780639b2cb5d81461094c5761043e565b8063883b455f11610205578063883b455f1461090c5780638ccdd289146109145780638d086da41461091c5780638d16a14a146109245780638da5cb5b1461092c5761043e565b80637ecebe00146108a457806383f3962a146108ca578063851e286e146108e75780638759c234146108ef5761043e565b8063446a2ec8116103475780636854d2a0116102cf5780637477341211610293578063747734121461082c5780637542ff951461083457806375cbee121461083c578063795be587146108595780637ba8c820146108855761043e565b80636854d2a0146107a75780636ab15071146107af5780636e7ce591146107d257806370a08231146107fe578063715018a6146108245761043e565b80635c42c733116103165780635c42c733146107205780635c5f7dae146107285780636035083f14610730578063653ec1341461075b578063676e5550146107815761043e565b8063446a2ec8146106e25780634f91440d146106ea578063533573b7146106f257806354fd4d50146107185761043e565b8063313ce567116103ca5780633950935111610399578063395093511461067a57806339c31e93146106a65780633a09bf44146106ae5780633ba0b9a9146106b65780633d94eb05146106be5761043e565b8063313ce567146105ea57806331f438a71461060857806333d266eb1461062b5780633644e515146106725761043e565b80631bf494a7116104115780631bf494a71461053f5780631e7ff8f614610547578063232e54151461058657806323b872dd1461058e5780633046c204146105c45761043e565b8063029d30401461044357806306fdde0314610468578063095ea7b3146104e557806318160ddd14610525575b600080fd5b6104666004803603604081101561045957600080fd5b5080359060200135610c47565b005b610470610c57565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104aa578181015183820152602001610492565b50505050905090810190601f1680156104d75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610511600480360360408110156104fb57600080fd5b506001600160a01b038135169060200135610cea565b604080519115158252519081900360200190f35b61052d610d01565b60408051918252519081900360200190f35b61052d610d07565b61056d6004803603602081101561055d57600080fd5b50356001600160a01b0316610d93565b6040805192835260208301919091528051918290030190f35b610466610df3565b610511600480360360608110156105a457600080fd5b506001600160a01b03813581169160208101359091169060400135610dff565b61052d600480360360208110156105da57600080fd5b50356001600160a01b0316610eb5565b6105f2610ec7565b6040805160ff9092168252519081900360200190f35b61052d6004803603604081101561061e57600080fd5b5080359060200135610ecc565b6106576004803603604081101561064157600080fd5b506001600160a01b038135169060200135610f07565b60408051921515835260208301919091528051918290030190f35b61052d611208565b6105116004803603604081101561069057600080fd5b506001600160a01b03813516906020013561120e565b61052d61124f565b61052d611255565b61052d61125b565b6106c6611318565b604080516001600160a01b039092168252519081900360200190f35b61052d611327565b61056d61132d565b61056d6004803603602081101561070857600080fd5b50356001600160a01b0316611343565b610470611530565b61052d61154f565b61052d611555565b6104666004803603606081101561074657600080fd5b5080359060208101359060400135151561155b565b61056d6004803603602081101561077157600080fd5b50356001600160a01b0316611756565b61052d6004803603602081101561079757600080fd5b50356001600160a01b031661176f565b61047061178a565b61052d600480360360408110156107c557600080fd5b50803590602001356117a5565b610466600480360360408110156107e857600080fd5b506001600160a01b0381351690602001356117ba565b61052d6004803603602081101561081457600080fd5b50356001600160a01b0316611a46565b610466611a61565b61052d611ac2565b6106c6611ac6565b61056d6004803603602081101561085257600080fd5b5035611ad5565b61056d6004803603604081101561086f57600080fd5b506001600160a01b038135169060200135611cab565b6104666004803603602081101561089b57600080fd5b50351515611ccf565b61052d600480360360208110156108ba57600080fd5b50356001600160a01b0316611cf3565b61052d600480360360208110156108e057600080fd5b5035611d0e565b61052d611d2b565b6104666004803603602081101561090557600080fd5b5035611dbe565b6106c6611dcc565b61052d611ddb565b61052d611de1565b610466611de7565b6106c6611df1565b610511611e05565b610470611e1b565b61056d611e68565b61052d611e76565b6104666004803603604081101561096a57600080fd5b506001600160a01b038135169060200135611e7c565b6105116004803603604081101561099657600080fd5b506001600160a01b038135169060200135611eaa565b610466611ee6565b610511600480360360408110156109ca57600080fd5b506001600160a01b038135169060200135611eff565b610466600480360360608110156109f657600080fd5b508035906001600160a01b0360208201358116916040013516611f0d565b61051160048036036040811015610a2a57600080fd5b506001600160a01b038135169060200135611fdb565b6106c6611fe9565b61046660048036036040811015610a5e57600080fd5b5080359060200135611ff8565b61052d612004565b61046661204b565b61046660048036036040811015610a9157600080fd5b5080359060200135612056565b61052d60048036036020811015610ab457600080fd5b5035612062565b610511612070565b610466600480360360e0811015610ad957600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612079565b61052d60048036036040811015610b2a57600080fd5b506001600160a01b03813581169160200135166121cd565b6105116121f8565b610466612201565b61052d60048036036040811015610b6857600080fd5b508035906020013561220c565b61052d60048036036020811015610b8b57600080fd5b50356001600160a01b031661221a565b61046660048036036040811015610bb157600080fd5b508035906020013561222c565b61046660048036036020811015610bd457600080fd5b5035612238565b61052d600480360360c0811015610bf157600080fd5b5080359060208101359060408101359060ff6060820135169060808101359060a00135612243565b61046660048036036020811015610c2f57600080fd5b50356001600160a01b031661242c565b610466612446565b610c538282600061245f565b5050565b6060610c6460065461260f565b60405160200180806e44656c65676174656420504f4c202360881b815250600f0182805190602001908083835b60208310610cb05780518252601f199092019160209182019101610c91565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405290505b90565b6000610cf73384846126ea565b5060015b92915050565b60025490565b6005546006546040805163072c21ef60e31b8152600481019290925251600092610d8e926001600160a01b03909116916339610f7891602480820192602092909190829003018186803b158015610d5d57600080fd5b505afa158015610d71573d6000803e3d6000fd5b505050506040513d6020811015610d8757600080fd5b5051612772565b905090565b6000806000610da184611a46565b90506000610dad61125b565b905081610dc157600093509150610dee9050565b610de8610dcc6127c9565b610ddc838563ffffffff6127f016565b9063ffffffff61281716565b93509150505b915091565b610dfd6001612839565b565b6000610e0c836001612906565b50610e18846001612906565b506000610e268585856129cf565b9050610e30612a21565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038881166024840152878116604484015260648301879052905192169163c08b3f9d9160848082019260009290919082900301818387803b158015610e9457600080fd5b505af1158015610ea8573d6000803e3d6000fd5b5092979650505050505050565b60146020526000908152604090205481565b601290565b6040805161190160f01b6020808301919091526022820194909452604280820193909352815180820390930183526062019052805191012090565b6000803381610f17866001612906565b506000610f2383611a46565b1115611168576000610f3783600c54612b5e565b9050801561116657600c546001600160a01b03841660009081526013602052604090205560035460ff166110b757610f70818285612bd3565b91508181111561102c57610fb48282038460405180604001604052806013815260200172496e737566666963656e74207265776172647360681b8152506001612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b0386811660248501528585036044850152905191169163b7721d2d91606480830192600092919082900301818387803b15801561101357600080fd5b505af1158015611027573d6000803e3d6000fd5b505050505b600061103784610d93565b506004805460065460408051637f88a95760e01b8152938401919091526001600160a01b0388811660248501526044840185905290519394501691637f88a9579160648082019260009290919082900301818387803b15801561109957600080fd5b505af11580156110ad573d6000803e3d6000fd5b5050505050611166565b6110ef818460405180604001604052806013815260200172496e737566666963656e74207265776172647360681b8152506001612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b03868116602485015260448401859052905191169163b7721d2d91606480830192600092919082900301818387803b15801561114d57600080fd5b505af1158015611161573d6000803e3d6000fd5b505050505b505b60006111758784886129cf565b905061117f612a21565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038a811660248401528681166044840152606483018a9052905192169163c08b3f9d9160848082019260009290919082900301818387803b1580156111e357600080fd5b505af11580156111f7573d6000803e3d6000fd5b509299939850929650505050505050565b60195490565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610cf791859061124a908663ffffffff61304616565b6126ea565b60075481565b600d5481565b600080611266610d01565b905060006112726127c9565b9050811561130f5760055460065460408051637f4b432360e01b815260048101929092525161130a928592610ddc9286926001600160a01b031691637f4b4323916024808301926020929190829003018186803b1580156112d257600080fd5b505afa1580156112e6573d6000803e3d6000fd5b505050506040513d60208110156112fc57600080fd5b50519063ffffffff6127f016565b611311565b805b9250505090565b6004546001600160a01b031681565b600c5481565b60008061133b336000613058565b915091509091565b600080600061135184611a46565b905080611365575060009150819050610dee565b600061136f610d01565b60055460065460408051637f4b432360e01b81526004810192909252519293506000926001600160a01b0390921691637f4b432391602480820192602092909190829003018186803b1580156113c457600080fd5b505afa1580156113d8573d6000803e3d6000fd5b505050506040513d60208110156113ee57600080fd5b5051905061140682610ddc838663ffffffff6127f016565b6005546006546040805163072c21ef60e31b81526004810192909252519297506000926001600160a01b03909216916339610f7891602480820192602092909190829003018186803b15801561145b57600080fd5b505afa15801561146f573d6000803e3d6000fd5b505050506040513d602081101561148557600080fd5b5051600c54909150811580159061149b57508315155b156114d2576114cf6114c285610ddc856a084595161401484a00000063ffffffff6127f016565b829063ffffffff61304616565b90505b6001600160a01b03881660009081526013602052604090205480821115611525576115226a084595161401484a000000610ddc88611516868663ffffffff6131c816565b9063ffffffff6127f016565b96505b505050505050915091565b6040805180820190915260058152640322e332e360dc1b602082015290565b600f5481565b60065481565b6000806115698585856131dd565b336000908152601460205260408120549294509092509061159190600163ffffffff61304616565b905061159b613edd565b6040518060400160405280848152602001600560009054906101000a90046001600160a01b03166001600160a01b031663900cf0cf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115fa57600080fd5b505afa15801561160e573d6000803e3d6000fd5b505050506040513d602081101561162457600080fd5b505190523360008181526015602090815260408083208784528252808320855181558583015160019091015592825260149052208390559050611665612a21565b60065460408051632a9b5b4160e11b81526004810192909252336024830152604482018a90526064820187905260848201859052516001600160a01b039290921691635536b6829160a48082019260009290919082900301818387803b1580156116ce57600080fd5b505af11580156116e2573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b15801561173557600080fd5b505af1158015611749573d6000803e3d6000fd5b5050505050505050505050565b6012602052600090815260409020805460019091015482565b60006117828261177d610d07565b612b5e565b90505b919050565b6040805180820190915260018152603160f81b602082015290565b60006117b3838360006133a9565b9392505050565b6117c2611e05565b6117cb57600080fd5b6117d6826001612906565b506000806117e384610d93565b9150915082821015611831576040805162461bcd60e51b815260206004820152601260248201527109ad2cee4c2e8d2dcce40e8dede40daeac6d60731b604482015290519081900360640190fd5b600061183b6127c9565b9050600061185383610ddc878563ffffffff6127f016565b905061185f8682613523565b60055460065460408051629ff11560e81b815260048101929092526000888103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b1580156118b557600080fd5b505af11580156118c9573d6000803e3d6000fd5b5050600d546118e1925090508663ffffffff6131c816565b600d55600480546006546040805163f1382b5360e01b8152938401919091526001600160a01b0389811660248501526044840189905260648401859052905191169163f1382b5391608480830192600092919082900301818387803b15801561194957600080fd5b505af115801561195d573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b1580156119b057600080fd5b505af11580156119c4573d6000803e3d6000fd5b5050600480546006546040805163302df4df60e11b8152938401919091526001600160a01b038b81166024850152604484018b905290519116935063605be9be9250606480830192600092919082900301818387803b158015611a2657600080fd5b505af1158015611a3a573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b031660009081526020819052604090205490565b611a69611e05565b611a7257600080fd5b60035460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360038054610100600160a81b0319169055565b4690565b6005546001600160a01b031681565b6000806000611ae3336135ca565b90506000611af7858363ffffffff61304616565b90506000611b06828333612bd3565b9050818114611b52576040805162461bcd60e51b815260206004820152601360248201527265786368616e67652072617465206e6f74203160681b604482015290519081900360640190fd5b6000611b5d33610d93565b506004805460065460408051637f88a95760e01b81529384019190915233602484015260448301849052519293506001600160a01b031691637f88a9579160648082019260009290919082900301818387803b158015611bbc57600080fd5b505af1158015611bd0573d6000803e3d6000fd5b505060055460065460408051624c025560e81b81526004810192909252602482018c9052336044830152516001600160a01b039092169350634c02550092506064808201926020929091908290030181600087803b158015611c3157600080fd5b505af1158015611c45573d6000803e3d6000fd5b505050506040513d6020811015611c5b57600080fd5b5051611c9f576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b50935090915050915091565b60156020908152600092835260408084209091529082529020805460019091015482565b611cd7611e05565b611ce057600080fd5b600e805460ff1916911515919091179055565b6001600160a01b031660009081526018602052604090205490565b600080611d1c336001613058565b5090506117828384600161155b565b600080611d36610c57565b805160209182012060408051808201825260018152603160f81b93019290925290519091507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690806052613f4a8239604051908190036052019020601d5550601b829055601c819055611da7611ac2565b601a55611db2613678565b60198190559250505090565b611dc98160016136d1565b50565b6016546001600160a01b031681565b60085481565b60105481565b610dfd6000612839565b60035461010090046001600160a01b031690565b60035461010090046001600160a01b0316331490565b6060611e2860065461260f565b604051602001808063191413d360e21b815250600401828051906020019080838360208310610cb05780518252601f199092019160209182019101610c91565b60008061133b336001613058565b600a5481565b611e84611e05565b611e8d57600080fd5b611e98826001612906565b50611ea581600084612bd3565b505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610cf791859061124a908663ffffffff6131c816565b611eee611e05565b611ef757600080fd5b610dfd6137c1565b6000610cf7838360006137cd565b600354600160a81b900460ff1615611f5d576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6003805460ff60a81b1916600160a81b1790556006839055600480546001600160a01b038085166001600160a01b0319928316179092556005805492841692909116919091179055611fae8161385b565b611fb6612a21565b50611fbf6138d5565b50600e805460ff19166001179055611fd5611d2b565b50505050565b6000610cf7838360016137cd565b6017546001600160a01b031681565b610c538282600161245f565b60008061200f6127c9565b905060086006541015612023579050610ce7565b60105480156120455761130a81610ddc84600f546127f090919063ffffffff16565b50919050565b611dc9336000612906565b610c538282600061155b565b600061178260195483610ecc565b60035460ff1681565b834211156120ce576040805162461bcd60e51b815260206004820152601760248201527f45524332363132457870697265645369676e6174757265000000000000000000604482015290519081900360640190fd5b60006040518080613ef860529139605201905060405180910390208888886120f58c613a4f565b604080516020808201979097526001600160a01b0395861681830152939094166060840152608083019190915260a082015260c08082018990528251808303909101815260e090910190915280519101209050600061215382612062565b9050600061216382878787613a72565b9050896001600160a01b0316816001600160a01b0316146121c2576040805162461bcd60e51b815260206004820152601460248201527322a921991b189924b73b30b634b229b4b3b732b960611b604482015290519081900360640190fd5b611a3a8a8a8a6126ea565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600e5460ff1681565b611dc9336001612906565b60006117b3838360016133a9565b60136020526000908152604090205481565b610c538282600161155b565b611dc98160006136d1565b60008061224e6138d5565b60408051623f675f60e91b815233600482015290519192506000916001600160a01b03841691637ecebe00916024808301926020929190829003018186803b15801561229957600080fd5b505afa1580156122ad573d6000803e3d6000fd5b505050506040513d60208110156122c357600080fd5b50516005546040805163d505accf60e01b81523360048201526001600160a01b039283166024820152604481018d9052606481018b905260ff8a16608482015260a4810189905260c4810188905290519293509084169163d505accf9160e48082019260009290919082900301818387803b15801561234157600080fd5b505af1158015612355573d6000803e3d6000fd5b505060408051623f675f60e91b815233600482015290516001850193506001600160a01b0386169250637ecebe0091602480820192602092909190829003018186803b1580156123a457600080fd5b505afa1580156123b8573d6000803e3d6000fd5b505050506040513d60208110156123ce57600080fd5b505114612413576040805162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081c195c9b5a5d60921b604482015290519081900360640190fd5b61241f898960016133a9565b9998505050505050505050565b612434611e05565b61243d57600080fd5b611dc98161385b565b61244e611e05565b61245757600080fd5b610dfd613b3a565b60008061246d8585856131dd565b91509150612479613edd565b503360009081526012602090815260409182902082518084019093528054808452600190910154918301919091526124b7908363ffffffff61304616565b81526005546040805163900cf0cf60e01b815290516001600160a01b039092169163900cf0cf91600480820192602092909190829003018186803b1580156124fe57600080fd5b505afa158015612512573d6000803e3d6000fd5b505050506040513d602081101561252857600080fd5b505160208281019182523360008181526012909252604080832085518155935160019094019390935560048054600654855163f1382b5360e01b8152928301526024820192909252604481018a90526064810187905292516001600160a01b0390911692839263f1382b539260848084019382900301818387803b1580156125af57600080fd5b505af11580156125c3573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561173557600080fd5b60608161263457506040805180820190915260018152600360fc1b6020820152611785565b8160005b811561264d5760049190911c90600101612638565b6060816040519080825280601f01601f19166020018201604052801561267a576020820181803883390190505b509050815b80156126e1576f181899199a1a9b1b9c1cb0b131b232b360811b86600f16601081106126a757fe5b1a60f81b8260018303815181106126ba57fe5b60200101906001600160f81b031916908160001a90535060049590951c946000190161267f565b50949350505050565b6001600160a01b0382166126fd57600080fd5b6001600160a01b03831661271057600080fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600c546000908215611782576000612788610d01565b905080156127c2576127bf6127b282610ddc876a084595161401484a00000063ffffffff6127f016565b839063ffffffff61304616565b91505b5092915050565b6000600860065410156127de57506064610ce7565b506c01431e0fae6d7217caa000000090565b6000826127ff57506000610cfb565b8282028284828161280c57fe5b04146117b357600080fd5b600080821161282557600080fd5b600082848161283057fe5b04949350505050565b612841613edd565b503360009081526012602090815260408083208151808301909252805482526001015491810191909152906128768284613b49565b3360008181526012602052604080822082815560010182905560048054600654835163302df4df60e11b81529283015260248201949094526044810185905290519394506001600160a01b039092169263605be9be92606480820193929182900301818387803b1580156128e957600080fd5b505af11580156128fd573d6000803e3d6000fd5b50505050505050565b600080612912846135ca565b905080156117b357612951818560405180604001604052806013815260200172496e737566666963656e74207265776172647360681b81525086612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b03878116602485015260448401859052905191169163b7721d2d91606480830192600092919082900301818387803b1580156129af57600080fd5b505af11580156129c3573d6000803e3d6000fd5b50505050905092915050565b60006129dc848484613d29565b6001600160a01b038416600090815260016020908152604080832033808552925290912054612a1791869161124a908663ffffffff6131c816565b5060019392505050565b6016546000906001600160a01b031680610d8e57600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8357600080fd5b505afa158015612a97573d6000803e3d6000fd5b505050506040513d6020811015612aad57600080fd5b5051604080516832bb32b73a39a43ab160b91b8152815190819003600901812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b158015612b1057600080fd5b505afa158015612b24573d6000803e3d6000fd5b505050506040513d6020811015612b3a57600080fd5b5051601680546001600160a01b0319166001600160a01b0383161790559050905090565b600080612b6a84611a46565b905080612b7b576000915050610cfb565b6001600160a01b03841660009081526013602052604090205483811415612ba757600092505050610cfb565b612bca6a084595161401484a000000610ddc84611516888663ffffffff6131c816565b95945050505050565b6000612bdd613df4565b600e5460ff16612c2d576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000612c3761125b565b90506000612c436127c9565b90506000612c5b83610ddc898563ffffffff6127f016565b905085811015612ca6576040805162461bcd60e51b8152602060048201526011602482015270546f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b6001600160a01b03851660009081526012602052604090205415612d00576040805162461bcd60e51b815260206004820152600c60248201526b13db99dbda5b99c8195e1a5d60a21b604482015290519081900360640190fd5b612d0a8582613e35565b612d1e82610ddc858463ffffffff6127f016565b60055460065460408051629ff11560e81b8152600481019290925260248201849052519299506001600160a01b0390911691639ff115009160448082019260009290919082900301818387803b158015612d7757600080fd5b505af1158015612d8b573d6000803e3d6000fd5b5050600d54612da3925090508863ffffffff61304616565b600d55600480546006546040805163c69d057360e01b8152938401919091526001600160a01b038881166024850152604484018b9052606484018590529051911691829163c69d05739160848082019260009290919082900301818387803b158015612e0e57600080fd5b505af1158015612e22573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612e6e57600080fd5b505af1158015612e82573d6000803e3d6000fd5b50999a9950505050505050505050565b80612f28576005546006546040805163bc8756a960e01b81526004810192909252602482018790526001600160a01b038681166044840152905192169163bc8756a9916064808201926020929091908290030181600087803b158015612ef757600080fd5b505af1158015612f0b573d6000803e3d6000fd5b505050506040513d6020811015612f2157600080fd5b5051612fb5565b6005546006546040805163c7f067cb60e01b81526004810192909252602482018790526001600160a01b038681166044840152905192169163c7f067cb916064808201926020929091908290030181600087803b158015612f8857600080fd5b505af1158015612f9c573d6000803e3d6000fd5b505050506040513d6020811015612fb257600080fd5b50515b829061303f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613004578181015183820152602001612fec565b50505050905090810190601f1680156130315780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505050565b6000828201838110156117b357600080fd5b6000806000613066856135ca565b9050600081156131be5761307c82600088612bd3565b905080821115613137576130bf8183038760405180604001604052806013815260200172496e737566666963656e74207265776172647360681b81525088612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b0389811660248501528486036044850152905191169163b7721d2d91606480830192600092919082900301818387803b15801561311e57600080fd5b505af1158015613132573d6000803e3d6000fd5b505050505b600061314287610d93565b506004805460065460408051637f88a95760e01b8152938401919091526001600160a01b038b811660248501526044840185905290519394501691637f88a9579160648082019260009290919082900301818387803b1580156131a457600080fd5b505af11580156131b8573d6000803e3d6000fd5b50505050505b9590945092505050565b6000828211156131d757600080fd5b50900390565b6000806000806131ec33610d93565b91509150816000141580156132015750868210155b613247576040805162461bcd60e51b8152602060048201526012602482015271151bdbc81b5d58da081c995c5d595cdd195960721b604482015290519081900360640190fd5b60006132516127c9565b9050600061326983610ddc8b8563ffffffff6127f016565b9050878111156132b4576040805162461bcd60e51b8152602060048201526011602482015270746f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b6132be3388612906565b506132c93382613523565b60055460065460408051629ff11560e81b8152600481019290925260008c8103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b15801561331f57600080fd5b505af1158015613333573d6000803e3d6000fd5b5050600d5461334b925090508a63ffffffff6131c816565b600d55600061336b61335b612004565b610ddc8c8663ffffffff6127f016565b600f54909150613381908b63ffffffff61304616565b600f55601054613397908263ffffffff61304616565b60105590999098509650505050505050565b60006133b53383612906565b506133c1848433612bd3565b9050816134575760055460065460408051636901b25360e01b8152600481019290925260248201849052336044830152516001600160a01b0390921691636901b253916064808201926020929091908290030181600087803b15801561342657600080fd5b505af115801561343a573d6000803e3d6000fd5b505050506040513d602081101561345057600080fd5b50516134e1565b60055460065460408051624c025560e81b8152600481019290925260248201849052336044830152516001600160a01b0390921691634c025500916064808201926020929091908290030181600087803b1580156134b457600080fd5b505af11580156134c8573d6000803e3d6000fd5b505050506040513d60208110156134de57600080fd5b50515b6117b3576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b6001600160a01b03821661353657600080fd5b600254613549908263ffffffff6131c816565b6002556001600160a01b038216600090815260208190526040902054613575908263ffffffff6131c816565b6001600160a01b038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b600080613641600560009054906101000a90046001600160a01b03166001600160a01b0316637ed4b27c6006546040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561362d57600080fd5b505af1158015610d71573d6000803e3d6000fd5b9050600061364f8483612b5e565b600c8390556001600160a01b038516600090815260136020526040902092909255509050919050565b6000601d54601b54601c5461368b611ac2565b6040805160208082019690965280820194909452606084019290925260808301523060a0808401919091528151808403909101815260c090920190528051910120905090565b6136d9613edd565b5033600090815260156020908152604080832085845282528083208151808301909252805482526001015491810191909152906137168284613b49565b3360009081526015602090815260408083208884529091528120818155600101559050613741612a21565b60065460408051636e699d8760e01b815260048101929092523360248301526044820184905260648201879052516001600160a01b039290921691636e699d879160848082019260009290919082900301818387803b1580156137a357600080fd5b505af11580156137b7573d6000803e3d6000fd5b5050505050505050565b6003805460ff19169055565b336137d88483612906565b506137e38183612906565b506137ef818585613d29565b6137f7612a21565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038481166024840152878116604484015260648301879052905192169163c08b3f9d9160848082019260009290919082900301818387803b1580156137a357600080fd5b6001600160a01b03811661386e57600080fd5b6003546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6017546000906001600160a01b031680610d8e57600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b15801561393757600080fd5b505afa15801561394b573d6000803e3d6000fd5b505050506040513d602081101561396157600080fd5b505160408051621c1bdb60ea1b8152815190819003600301812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b1580156139be57600080fd5b505afa1580156139d2573d6000803e3d6000fd5b505050506040513d60208110156139e857600080fd5b505190506001600160a01b038116613a2f576040805162461bcd60e51b81526020600482015260056024820152641d5b9cd95d60da1b604482015290519081900360640190fd5b601780546001600160a01b0319166001600160a01b038316179055919050565b6001600160a01b0316600090815260186020526040902080546001810190915590565b60008060018686868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613ad2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612bca576040805162461bcd60e51b815260206004820152601d60248201527f7369676e617475726520766572696669636174696f6e206661696c6564000000604482015290519081900360640190fd5b6003805460ff19166001179055565b81516005546040805163900cf0cf60e01b81529051600093926001600160a01b03169163900cf0cf916004808301926020929190829003018186803b158015613b9157600080fd5b505afa158015613ba5573d6000803e3d6000fd5b505050506040513d6020811015613bbb57600080fd5b50516005546040805163a7ab696160e01b81529051613c40926001600160a01b03169163a7ab6961916004808301926020929190829003018186803b158015613c0357600080fd5b505afa158015613c17573d6000803e3d6000fd5b505050506040513d6020811015613c2d57600080fd5b505160208701519063ffffffff61304616565b11158015613c4e5750600081115b613c9f576040805162461bcd60e51b815260206004820152601c60248201527f496e636f6d706c657465207769746864726177616c20706572696f6400000000604482015290519081900360640190fd5b6000613cb8613cac6127c9565b610ddc84611516612004565b601054909150613cce908363ffffffff6131c816565b601055600f54613ce4908263ffffffff6131c816565b600f81905550613d21813360405180604001604052806013815260200172496e737566666963656e74207265776172647360681b81525087612e92565b949350505050565b6001600160a01b038216613d3c57600080fd5b6001600160a01b038316600090815260208190526040902054613d65908263ffffffff6131c816565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613d9a908263ffffffff61304616565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60035460ff1615610dfd576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6001600160a01b038216613e4857600080fd5b600254613e5b908263ffffffff61304616565b6002556001600160a01b038216600090815260208190526040902054613e87908263ffffffff61304616565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60405180604001604052806000815260200160008152509056fe5065726d69742861646472657373206f776e65722c61646472657373207370656e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63652c75696e7432353620646561646c696e6529454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429a265627a7a7231582018d67c5c5a0fc5ddff7caa325cc3c9110c1df533d6dca990120c17a992adb93c64736f6c63430005110032
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061043e5760003560e01c80637ecebe0011610236578063b60c76fa1161013b578063dd62ed3e116100c3578063e570b78b11610087578063e570b78b14610b9b578063e97fddc214610bbe578063eaf43bb514610bdb578063f2fde38b14610c19578063f83d08ba14610c3f5761043e565b8063dd62ed3e14610b14578063df5cf72314610b42578063e0db556b14610b4a578063e4457a8a14610b52578063e4cd1aec14610b755761043e565b8063c7b8981c1161010a578063c7b8981c14610a73578063c83ec04d14610a7b578063c8f1ecd814610a9e578063cf30901214610abb578063d505accf14610ac35761043e565b8063b60c76fa14610a14578063b6658d0714610a40578063b89b63c114610a48578063bfb18f2914610a6b5761043e565b80638f32d59b116101be578063a0c1ca341161018d578063a0c1ca3414610954578063a457c2d714610980578063a69df4b5146109ac578063a9059cbb146109b4578063b4988fd0146109e05761043e565b80638f32d59b1461093457806395d89b411461093c5780639ad5f5a4146109445780639b2cb5d81461094c5761043e565b8063883b455f11610205578063883b455f1461090c5780638ccdd289146109145780638d086da41461091c5780638d16a14a146109245780638da5cb5b1461092c5761043e565b80637ecebe00146108a457806383f3962a146108ca578063851e286e146108e75780638759c234146108ef5761043e565b8063446a2ec8116103475780636854d2a0116102cf5780637477341211610293578063747734121461082c5780637542ff951461083457806375cbee121461083c578063795be587146108595780637ba8c820146108855761043e565b80636854d2a0146107a75780636ab15071146107af5780636e7ce591146107d257806370a08231146107fe578063715018a6146108245761043e565b80635c42c733116103165780635c42c733146107205780635c5f7dae146107285780636035083f14610730578063653ec1341461075b578063676e5550146107815761043e565b8063446a2ec8146106e25780634f91440d146106ea578063533573b7146106f257806354fd4d50146107185761043e565b8063313ce567116103ca5780633950935111610399578063395093511461067a57806339c31e93146106a65780633a09bf44146106ae5780633ba0b9a9146106b65780633d94eb05146106be5761043e565b8063313ce567146105ea57806331f438a71461060857806333d266eb1461062b5780633644e515146106725761043e565b80631bf494a7116104115780631bf494a71461053f5780631e7ff8f614610547578063232e54151461058657806323b872dd1461058e5780633046c204146105c45761043e565b8063029d30401461044357806306fdde0314610468578063095ea7b3146104e557806318160ddd14610525575b600080fd5b6104666004803603604081101561045957600080fd5b5080359060200135610c47565b005b610470610c57565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104aa578181015183820152602001610492565b50505050905090810190601f1680156104d75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610511600480360360408110156104fb57600080fd5b506001600160a01b038135169060200135610cea565b604080519115158252519081900360200190f35b61052d610d01565b60408051918252519081900360200190f35b61052d610d07565b61056d6004803603602081101561055d57600080fd5b50356001600160a01b0316610d93565b6040805192835260208301919091528051918290030190f35b610466610df3565b610511600480360360608110156105a457600080fd5b506001600160a01b03813581169160208101359091169060400135610dff565b61052d600480360360208110156105da57600080fd5b50356001600160a01b0316610eb5565b6105f2610ec7565b6040805160ff9092168252519081900360200190f35b61052d6004803603604081101561061e57600080fd5b5080359060200135610ecc565b6106576004803603604081101561064157600080fd5b506001600160a01b038135169060200135610f07565b60408051921515835260208301919091528051918290030190f35b61052d611208565b6105116004803603604081101561069057600080fd5b506001600160a01b03813516906020013561120e565b61052d61124f565b61052d611255565b61052d61125b565b6106c6611318565b604080516001600160a01b039092168252519081900360200190f35b61052d611327565b61056d61132d565b61056d6004803603602081101561070857600080fd5b50356001600160a01b0316611343565b610470611530565b61052d61154f565b61052d611555565b6104666004803603606081101561074657600080fd5b5080359060208101359060400135151561155b565b61056d6004803603602081101561077157600080fd5b50356001600160a01b0316611756565b61052d6004803603602081101561079757600080fd5b50356001600160a01b031661176f565b61047061178a565b61052d600480360360408110156107c557600080fd5b50803590602001356117a5565b610466600480360360408110156107e857600080fd5b506001600160a01b0381351690602001356117ba565b61052d6004803603602081101561081457600080fd5b50356001600160a01b0316611a46565b610466611a61565b61052d611ac2565b6106c6611ac6565b61056d6004803603602081101561085257600080fd5b5035611ad5565b61056d6004803603604081101561086f57600080fd5b506001600160a01b038135169060200135611cab565b6104666004803603602081101561089b57600080fd5b50351515611ccf565b61052d600480360360208110156108ba57600080fd5b50356001600160a01b0316611cf3565b61052d600480360360208110156108e057600080fd5b5035611d0e565b61052d611d2b565b6104666004803603602081101561090557600080fd5b5035611dbe565b6106c6611dcc565b61052d611ddb565b61052d611de1565b610466611de7565b6106c6611df1565b610511611e05565b610470611e1b565b61056d611e68565b61052d611e76565b6104666004803603604081101561096a57600080fd5b506001600160a01b038135169060200135611e7c565b6105116004803603604081101561099657600080fd5b506001600160a01b038135169060200135611eaa565b610466611ee6565b610511600480360360408110156109ca57600080fd5b506001600160a01b038135169060200135611eff565b610466600480360360608110156109f657600080fd5b508035906001600160a01b0360208201358116916040013516611f0d565b61051160048036036040811015610a2a57600080fd5b506001600160a01b038135169060200135611fdb565b6106c6611fe9565b61046660048036036040811015610a5e57600080fd5b5080359060200135611ff8565b61052d612004565b61046661204b565b61046660048036036040811015610a9157600080fd5b5080359060200135612056565b61052d60048036036020811015610ab457600080fd5b5035612062565b610511612070565b610466600480360360e0811015610ad957600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612079565b61052d60048036036040811015610b2a57600080fd5b506001600160a01b03813581169160200135166121cd565b6105116121f8565b610466612201565b61052d60048036036040811015610b6857600080fd5b508035906020013561220c565b61052d60048036036020811015610b8b57600080fd5b50356001600160a01b031661221a565b61046660048036036040811015610bb157600080fd5b508035906020013561222c565b61046660048036036020811015610bd457600080fd5b5035612238565b61052d600480360360c0811015610bf157600080fd5b5080359060208101359060408101359060ff6060820135169060808101359060a00135612243565b61046660048036036020811015610c2f57600080fd5b50356001600160a01b031661242c565b610466612446565b610c538282600061245f565b5050565b6060610c6460065461260f565b60405160200180806e44656c65676174656420504f4c202360881b815250600f0182805190602001908083835b60208310610cb05780518252601f199092019160209182019101610c91565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405290505b90565b6000610cf73384846126ea565b5060015b92915050565b60025490565b6005546006546040805163072c21ef60e31b8152600481019290925251600092610d8e926001600160a01b03909116916339610f7891602480820192602092909190829003018186803b158015610d5d57600080fd5b505afa158015610d71573d6000803e3d6000fd5b505050506040513d6020811015610d8757600080fd5b5051612772565b905090565b6000806000610da184611a46565b90506000610dad61125b565b905081610dc157600093509150610dee9050565b610de8610dcc6127c9565b610ddc838563ffffffff6127f016565b9063ffffffff61281716565b93509150505b915091565b610dfd6001612839565b565b6000610e0c836001612906565b50610e18846001612906565b506000610e268585856129cf565b9050610e30612a21565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038881166024840152878116604484015260648301879052905192169163c08b3f9d9160848082019260009290919082900301818387803b158015610e9457600080fd5b505af1158015610ea8573d6000803e3d6000fd5b5092979650505050505050565b60146020526000908152604090205481565b601290565b6040805161190160f01b6020808301919091526022820194909452604280820193909352815180820390930183526062019052805191012090565b6000803381610f17866001612906565b506000610f2383611a46565b1115611168576000610f3783600c54612b5e565b9050801561116657600c546001600160a01b03841660009081526013602052604090205560035460ff166110b757610f70818285612bd3565b91508181111561102c57610fb48282038460405180604001604052806013815260200172496e737566666963656e74207265776172647360681b8152506001612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b0386811660248501528585036044850152905191169163b7721d2d91606480830192600092919082900301818387803b15801561101357600080fd5b505af1158015611027573d6000803e3d6000fd5b505050505b600061103784610d93565b506004805460065460408051637f88a95760e01b8152938401919091526001600160a01b0388811660248501526044840185905290519394501691637f88a9579160648082019260009290919082900301818387803b15801561109957600080fd5b505af11580156110ad573d6000803e3d6000fd5b5050505050611166565b6110ef818460405180604001604052806013815260200172496e737566666963656e74207265776172647360681b8152506001612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b03868116602485015260448401859052905191169163b7721d2d91606480830192600092919082900301818387803b15801561114d57600080fd5b505af1158015611161573d6000803e3d6000fd5b505050505b505b60006111758784886129cf565b905061117f612a21565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038a811660248401528681166044840152606483018a9052905192169163c08b3f9d9160848082019260009290919082900301818387803b1580156111e357600080fd5b505af11580156111f7573d6000803e3d6000fd5b509299939850929650505050505050565b60195490565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610cf791859061124a908663ffffffff61304616565b6126ea565b60075481565b600d5481565b600080611266610d01565b905060006112726127c9565b9050811561130f5760055460065460408051637f4b432360e01b815260048101929092525161130a928592610ddc9286926001600160a01b031691637f4b4323916024808301926020929190829003018186803b1580156112d257600080fd5b505afa1580156112e6573d6000803e3d6000fd5b505050506040513d60208110156112fc57600080fd5b50519063ffffffff6127f016565b611311565b805b9250505090565b6004546001600160a01b031681565b600c5481565b60008061133b336000613058565b915091509091565b600080600061135184611a46565b905080611365575060009150819050610dee565b600061136f610d01565b60055460065460408051637f4b432360e01b81526004810192909252519293506000926001600160a01b0390921691637f4b432391602480820192602092909190829003018186803b1580156113c457600080fd5b505afa1580156113d8573d6000803e3d6000fd5b505050506040513d60208110156113ee57600080fd5b5051905061140682610ddc838663ffffffff6127f016565b6005546006546040805163072c21ef60e31b81526004810192909252519297506000926001600160a01b03909216916339610f7891602480820192602092909190829003018186803b15801561145b57600080fd5b505afa15801561146f573d6000803e3d6000fd5b505050506040513d602081101561148557600080fd5b5051600c54909150811580159061149b57508315155b156114d2576114cf6114c285610ddc856a084595161401484a00000063ffffffff6127f016565b829063ffffffff61304616565b90505b6001600160a01b03881660009081526013602052604090205480821115611525576115226a084595161401484a000000610ddc88611516868663ffffffff6131c816565b9063ffffffff6127f016565b96505b505050505050915091565b6040805180820190915260058152640322e332e360dc1b602082015290565b600f5481565b60065481565b6000806115698585856131dd565b336000908152601460205260408120549294509092509061159190600163ffffffff61304616565b905061159b613edd565b6040518060400160405280848152602001600560009054906101000a90046001600160a01b03166001600160a01b031663900cf0cf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115fa57600080fd5b505afa15801561160e573d6000803e3d6000fd5b505050506040513d602081101561162457600080fd5b505190523360008181526015602090815260408083208784528252808320855181558583015160019091015592825260149052208390559050611665612a21565b60065460408051632a9b5b4160e11b81526004810192909252336024830152604482018a90526064820187905260848201859052516001600160a01b039290921691635536b6829160a48082019260009290919082900301818387803b1580156116ce57600080fd5b505af11580156116e2573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b15801561173557600080fd5b505af1158015611749573d6000803e3d6000fd5b5050505050505050505050565b6012602052600090815260409020805460019091015482565b60006117828261177d610d07565b612b5e565b90505b919050565b6040805180820190915260018152603160f81b602082015290565b60006117b3838360006133a9565b9392505050565b6117c2611e05565b6117cb57600080fd5b6117d6826001612906565b506000806117e384610d93565b9150915082821015611831576040805162461bcd60e51b815260206004820152601260248201527109ad2cee4c2e8d2dcce40e8dede40daeac6d60731b604482015290519081900360640190fd5b600061183b6127c9565b9050600061185383610ddc878563ffffffff6127f016565b905061185f8682613523565b60055460065460408051629ff11560e81b815260048101929092526000888103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b1580156118b557600080fd5b505af11580156118c9573d6000803e3d6000fd5b5050600d546118e1925090508663ffffffff6131c816565b600d55600480546006546040805163f1382b5360e01b8152938401919091526001600160a01b0389811660248501526044840189905260648401859052905191169163f1382b5391608480830192600092919082900301818387803b15801561194957600080fd5b505af115801561195d573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b1580156119b057600080fd5b505af11580156119c4573d6000803e3d6000fd5b5050600480546006546040805163302df4df60e11b8152938401919091526001600160a01b038b81166024850152604484018b905290519116935063605be9be9250606480830192600092919082900301818387803b158015611a2657600080fd5b505af1158015611a3a573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b031660009081526020819052604090205490565b611a69611e05565b611a7257600080fd5b60035460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360038054610100600160a81b0319169055565b4690565b6005546001600160a01b031681565b6000806000611ae3336135ca565b90506000611af7858363ffffffff61304616565b90506000611b06828333612bd3565b9050818114611b52576040805162461bcd60e51b815260206004820152601360248201527265786368616e67652072617465206e6f74203160681b604482015290519081900360640190fd5b6000611b5d33610d93565b506004805460065460408051637f88a95760e01b81529384019190915233602484015260448301849052519293506001600160a01b031691637f88a9579160648082019260009290919082900301818387803b158015611bbc57600080fd5b505af1158015611bd0573d6000803e3d6000fd5b505060055460065460408051624c025560e81b81526004810192909252602482018c9052336044830152516001600160a01b039092169350634c02550092506064808201926020929091908290030181600087803b158015611c3157600080fd5b505af1158015611c45573d6000803e3d6000fd5b505050506040513d6020811015611c5b57600080fd5b5051611c9f576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b50935090915050915091565b60156020908152600092835260408084209091529082529020805460019091015482565b611cd7611e05565b611ce057600080fd5b600e805460ff1916911515919091179055565b6001600160a01b031660009081526018602052604090205490565b600080611d1c336001613058565b5090506117828384600161155b565b600080611d36610c57565b805160209182012060408051808201825260018152603160f81b93019290925290519091507fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690806052613f4a8239604051908190036052019020601d5550601b829055601c819055611da7611ac2565b601a55611db2613678565b60198190559250505090565b611dc98160016136d1565b50565b6016546001600160a01b031681565b60085481565b60105481565b610dfd6000612839565b60035461010090046001600160a01b031690565b60035461010090046001600160a01b0316331490565b6060611e2860065461260f565b604051602001808063191413d360e21b815250600401828051906020019080838360208310610cb05780518252601f199092019160209182019101610c91565b60008061133b336001613058565b600a5481565b611e84611e05565b611e8d57600080fd5b611e98826001612906565b50611ea581600084612bd3565b505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610cf791859061124a908663ffffffff6131c816565b611eee611e05565b611ef757600080fd5b610dfd6137c1565b6000610cf7838360006137cd565b600354600160a81b900460ff1615611f5d576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6003805460ff60a81b1916600160a81b1790556006839055600480546001600160a01b038085166001600160a01b0319928316179092556005805492841692909116919091179055611fae8161385b565b611fb6612a21565b50611fbf6138d5565b50600e805460ff19166001179055611fd5611d2b565b50505050565b6000610cf7838360016137cd565b6017546001600160a01b031681565b610c538282600161245f565b60008061200f6127c9565b905060086006541015612023579050610ce7565b60105480156120455761130a81610ddc84600f546127f090919063ffffffff16565b50919050565b611dc9336000612906565b610c538282600061155b565b600061178260195483610ecc565b60035460ff1681565b834211156120ce576040805162461bcd60e51b815260206004820152601760248201527f45524332363132457870697265645369676e6174757265000000000000000000604482015290519081900360640190fd5b60006040518080613ef860529139605201905060405180910390208888886120f58c613a4f565b604080516020808201979097526001600160a01b0395861681830152939094166060840152608083019190915260a082015260c08082018990528251808303909101815260e090910190915280519101209050600061215382612062565b9050600061216382878787613a72565b9050896001600160a01b0316816001600160a01b0316146121c2576040805162461bcd60e51b815260206004820152601460248201527322a921991b189924b73b30b634b229b4b3b732b960611b604482015290519081900360640190fd5b611a3a8a8a8a6126ea565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600e5460ff1681565b611dc9336001612906565b60006117b3838360016133a9565b60136020526000908152604090205481565b610c538282600161155b565b611dc98160006136d1565b60008061224e6138d5565b60408051623f675f60e91b815233600482015290519192506000916001600160a01b03841691637ecebe00916024808301926020929190829003018186803b15801561229957600080fd5b505afa1580156122ad573d6000803e3d6000fd5b505050506040513d60208110156122c357600080fd5b50516005546040805163d505accf60e01b81523360048201526001600160a01b039283166024820152604481018d9052606481018b905260ff8a16608482015260a4810189905260c4810188905290519293509084169163d505accf9160e48082019260009290919082900301818387803b15801561234157600080fd5b505af1158015612355573d6000803e3d6000fd5b505060408051623f675f60e91b815233600482015290516001850193506001600160a01b0386169250637ecebe0091602480820192602092909190829003018186803b1580156123a457600080fd5b505afa1580156123b8573d6000803e3d6000fd5b505050506040513d60208110156123ce57600080fd5b505114612413576040805162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081c195c9b5a5d60921b604482015290519081900360640190fd5b61241f898960016133a9565b9998505050505050505050565b612434611e05565b61243d57600080fd5b611dc98161385b565b61244e611e05565b61245757600080fd5b610dfd613b3a565b60008061246d8585856131dd565b91509150612479613edd565b503360009081526012602090815260409182902082518084019093528054808452600190910154918301919091526124b7908363ffffffff61304616565b81526005546040805163900cf0cf60e01b815290516001600160a01b039092169163900cf0cf91600480820192602092909190829003018186803b1580156124fe57600080fd5b505afa158015612512573d6000803e3d6000fd5b505050506040513d602081101561252857600080fd5b505160208281019182523360008181526012909252604080832085518155935160019094019390935560048054600654855163f1382b5360e01b8152928301526024820192909252604481018a90526064810187905292516001600160a01b0390911692839263f1382b539260848084019382900301818387803b1580156125af57600080fd5b505af11580156125c3573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561173557600080fd5b60608161263457506040805180820190915260018152600360fc1b6020820152611785565b8160005b811561264d5760049190911c90600101612638565b6060816040519080825280601f01601f19166020018201604052801561267a576020820181803883390190505b509050815b80156126e1576f181899199a1a9b1b9c1cb0b131b232b360811b86600f16601081106126a757fe5b1a60f81b8260018303815181106126ba57fe5b60200101906001600160f81b031916908160001a90535060049590951c946000190161267f565b50949350505050565b6001600160a01b0382166126fd57600080fd5b6001600160a01b03831661271057600080fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600c546000908215611782576000612788610d01565b905080156127c2576127bf6127b282610ddc876a084595161401484a00000063ffffffff6127f016565b839063ffffffff61304616565b91505b5092915050565b6000600860065410156127de57506064610ce7565b506c01431e0fae6d7217caa000000090565b6000826127ff57506000610cfb565b8282028284828161280c57fe5b04146117b357600080fd5b600080821161282557600080fd5b600082848161283057fe5b04949350505050565b612841613edd565b503360009081526012602090815260408083208151808301909252805482526001015491810191909152906128768284613b49565b3360008181526012602052604080822082815560010182905560048054600654835163302df4df60e11b81529283015260248201949094526044810185905290519394506001600160a01b039092169263605be9be92606480820193929182900301818387803b1580156128e957600080fd5b505af11580156128fd573d6000803e3d6000fd5b50505050505050565b600080612912846135ca565b905080156117b357612951818560405180604001604052806013815260200172496e737566666963656e74207265776172647360681b81525086612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b03878116602485015260448401859052905191169163b7721d2d91606480830192600092919082900301818387803b1580156129af57600080fd5b505af11580156129c3573d6000803e3d6000fd5b50505050905092915050565b60006129dc848484613d29565b6001600160a01b038416600090815260016020908152604080832033808552925290912054612a1791869161124a908663ffffffff6131c816565b5060019392505050565b6016546000906001600160a01b031680610d8e57600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8357600080fd5b505afa158015612a97573d6000803e3d6000fd5b505050506040513d6020811015612aad57600080fd5b5051604080516832bb32b73a39a43ab160b91b8152815190819003600901812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b158015612b1057600080fd5b505afa158015612b24573d6000803e3d6000fd5b505050506040513d6020811015612b3a57600080fd5b5051601680546001600160a01b0319166001600160a01b0383161790559050905090565b600080612b6a84611a46565b905080612b7b576000915050610cfb565b6001600160a01b03841660009081526013602052604090205483811415612ba757600092505050610cfb565b612bca6a084595161401484a000000610ddc84611516888663ffffffff6131c816565b95945050505050565b6000612bdd613df4565b600e5460ff16612c2d576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000612c3761125b565b90506000612c436127c9565b90506000612c5b83610ddc898563ffffffff6127f016565b905085811015612ca6576040805162461bcd60e51b8152602060048201526011602482015270546f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b6001600160a01b03851660009081526012602052604090205415612d00576040805162461bcd60e51b815260206004820152600c60248201526b13db99dbda5b99c8195e1a5d60a21b604482015290519081900360640190fd5b612d0a8582613e35565b612d1e82610ddc858463ffffffff6127f016565b60055460065460408051629ff11560e81b8152600481019290925260248201849052519299506001600160a01b0390911691639ff115009160448082019260009290919082900301818387803b158015612d7757600080fd5b505af1158015612d8b573d6000803e3d6000fd5b5050600d54612da3925090508863ffffffff61304616565b600d55600480546006546040805163c69d057360e01b8152938401919091526001600160a01b038881166024850152604484018b9052606484018590529051911691829163c69d05739160848082019260009290919082900301818387803b158015612e0e57600080fd5b505af1158015612e22573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015612e6e57600080fd5b505af1158015612e82573d6000803e3d6000fd5b50999a9950505050505050505050565b80612f28576005546006546040805163bc8756a960e01b81526004810192909252602482018790526001600160a01b038681166044840152905192169163bc8756a9916064808201926020929091908290030181600087803b158015612ef757600080fd5b505af1158015612f0b573d6000803e3d6000fd5b505050506040513d6020811015612f2157600080fd5b5051612fb5565b6005546006546040805163c7f067cb60e01b81526004810192909252602482018790526001600160a01b038681166044840152905192169163c7f067cb916064808201926020929091908290030181600087803b158015612f8857600080fd5b505af1158015612f9c573d6000803e3d6000fd5b505050506040513d6020811015612fb257600080fd5b50515b829061303f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613004578181015183820152602001612fec565b50505050905090810190601f1680156130315780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5050505050565b6000828201838110156117b357600080fd5b6000806000613066856135ca565b9050600081156131be5761307c82600088612bd3565b905080821115613137576130bf8183038760405180604001604052806013815260200172496e737566666963656e74207265776172647360681b81525088612e92565b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b0389811660248501528486036044850152905191169163b7721d2d91606480830192600092919082900301818387803b15801561311e57600080fd5b505af1158015613132573d6000803e3d6000fd5b505050505b600061314287610d93565b506004805460065460408051637f88a95760e01b8152938401919091526001600160a01b038b811660248501526044840185905290519394501691637f88a9579160648082019260009290919082900301818387803b1580156131a457600080fd5b505af11580156131b8573d6000803e3d6000fd5b50505050505b9590945092505050565b6000828211156131d757600080fd5b50900390565b6000806000806131ec33610d93565b91509150816000141580156132015750868210155b613247576040805162461bcd60e51b8152602060048201526012602482015271151bdbc81b5d58da081c995c5d595cdd195960721b604482015290519081900360640190fd5b60006132516127c9565b9050600061326983610ddc8b8563ffffffff6127f016565b9050878111156132b4576040805162461bcd60e51b8152602060048201526011602482015270746f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b6132be3388612906565b506132c93382613523565b60055460065460408051629ff11560e81b8152600481019290925260008c8103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b15801561331f57600080fd5b505af1158015613333573d6000803e3d6000fd5b5050600d5461334b925090508a63ffffffff6131c816565b600d55600061336b61335b612004565b610ddc8c8663ffffffff6127f016565b600f54909150613381908b63ffffffff61304616565b600f55601054613397908263ffffffff61304616565b60105590999098509650505050505050565b60006133b53383612906565b506133c1848433612bd3565b9050816134575760055460065460408051636901b25360e01b8152600481019290925260248201849052336044830152516001600160a01b0390921691636901b253916064808201926020929091908290030181600087803b15801561342657600080fd5b505af115801561343a573d6000803e3d6000fd5b505050506040513d602081101561345057600080fd5b50516134e1565b60055460065460408051624c025560e81b8152600481019290925260248201849052336044830152516001600160a01b0390921691634c025500916064808201926020929091908290030181600087803b1580156134b457600080fd5b505af11580156134c8573d6000803e3d6000fd5b505050506040513d60208110156134de57600080fd5b50515b6117b3576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b6001600160a01b03821661353657600080fd5b600254613549908263ffffffff6131c816565b6002556001600160a01b038216600090815260208190526040902054613575908263ffffffff6131c816565b6001600160a01b038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b600080613641600560009054906101000a90046001600160a01b03166001600160a01b0316637ed4b27c6006546040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561362d57600080fd5b505af1158015610d71573d6000803e3d6000fd5b9050600061364f8483612b5e565b600c8390556001600160a01b038516600090815260136020526040902092909255509050919050565b6000601d54601b54601c5461368b611ac2565b6040805160208082019690965280820194909452606084019290925260808301523060a0808401919091528151808403909101815260c090920190528051910120905090565b6136d9613edd565b5033600090815260156020908152604080832085845282528083208151808301909252805482526001015491810191909152906137168284613b49565b3360009081526015602090815260408083208884529091528120818155600101559050613741612a21565b60065460408051636e699d8760e01b815260048101929092523360248301526044820184905260648201879052516001600160a01b039290921691636e699d879160848082019260009290919082900301818387803b1580156137a357600080fd5b505af11580156137b7573d6000803e3d6000fd5b5050505050505050565b6003805460ff19169055565b336137d88483612906565b506137e38183612906565b506137ef818585613d29565b6137f7612a21565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038481166024840152878116604484015260648301879052905192169163c08b3f9d9160848082019260009290919082900301818387803b1580156137a357600080fd5b6001600160a01b03811661386e57600080fd5b6003546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6017546000906001600160a01b031680610d8e57600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b15801561393757600080fd5b505afa15801561394b573d6000803e3d6000fd5b505050506040513d602081101561396157600080fd5b505160408051621c1bdb60ea1b8152815190819003600301812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b1580156139be57600080fd5b505afa1580156139d2573d6000803e3d6000fd5b505050506040513d60208110156139e857600080fd5b505190506001600160a01b038116613a2f576040805162461bcd60e51b81526020600482015260056024820152641d5b9cd95d60da1b604482015290519081900360640190fd5b601780546001600160a01b0319166001600160a01b038316179055919050565b6001600160a01b0316600090815260186020526040902080546001810190915590565b60008060018686868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015613ad2573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612bca576040805162461bcd60e51b815260206004820152601d60248201527f7369676e617475726520766572696669636174696f6e206661696c6564000000604482015290519081900360640190fd5b6003805460ff19166001179055565b81516005546040805163900cf0cf60e01b81529051600093926001600160a01b03169163900cf0cf916004808301926020929190829003018186803b158015613b9157600080fd5b505afa158015613ba5573d6000803e3d6000fd5b505050506040513d6020811015613bbb57600080fd5b50516005546040805163a7ab696160e01b81529051613c40926001600160a01b03169163a7ab6961916004808301926020929190829003018186803b158015613c0357600080fd5b505afa158015613c17573d6000803e3d6000fd5b505050506040513d6020811015613c2d57600080fd5b505160208701519063ffffffff61304616565b11158015613c4e5750600081115b613c9f576040805162461bcd60e51b815260206004820152601c60248201527f496e636f6d706c657465207769746864726177616c20706572696f6400000000604482015290519081900360640190fd5b6000613cb8613cac6127c9565b610ddc84611516612004565b601054909150613cce908363ffffffff6131c816565b601055600f54613ce4908263ffffffff6131c816565b600f81905550613d21813360405180604001604052806013815260200172496e737566666963656e74207265776172647360681b81525087612e92565b949350505050565b6001600160a01b038216613d3c57600080fd5b6001600160a01b038316600090815260208190526040902054613d65908263ffffffff6131c816565b6001600160a01b038085166000908152602081905260408082209390935590841681522054613d9a908263ffffffff61304616565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60035460ff1615610dfd576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6001600160a01b038216613e4857600080fd5b600254613e5b908263ffffffff61304616565b6002556001600160a01b038216600090815260208190526040902054613e87908263ffffffff61304616565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60405180604001604052806000815260200160008152509056fe5065726d69742861646472657373206f776e65722c61646472657373207370656e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63652c75696e7432353620646561646c696e6529454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429a265627a7a7231582018d67c5c5a0fc5ddff7caa325cc3c9110c1df533d6dca990120c17a992adb93c64736f6c63430005110032
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.