Overview
FTM Balance
0 FTM
FTM Value
$0.00More Info
Private Name Tags
ContractCreator
Sponsored
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 50616513 | 700 days ago | IN | 0 FTM | 0.65992979 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
87212511 | 70 days ago | 713.14221152 FTM | ||||
87212480 | 70 days ago | 1,387.43487012 FTM | ||||
87212448 | 70 days ago | 461.31501031 FTM | ||||
87210783 | 70 days ago | 4,559.97579953 FTM | ||||
87207395 | 70 days ago | 23.35200458 FTM | ||||
87207301 | 70 days ago | 0.16524345 FTM | ||||
87204930 | 70 days ago | 10,814 FTM | ||||
87201217 | 70 days ago | 12.13350855 FTM | ||||
87201217 | 70 days ago | 10.9201577 FTM | ||||
87201217 | 70 days ago | 16.92662589 FTM | ||||
87201217 | 70 days ago | 12.14100432 FTM | ||||
87201217 | 70 days ago | 7.3286987 FTM | ||||
87201217 | 70 days ago | 23.89243009 FTM | ||||
87201217 | 70 days ago | 12.12379223 FTM | ||||
87201217 | 70 days ago | 12.14100432 FTM | ||||
87201217 | 70 days ago | 12.21449784 FTM | ||||
87201217 | 70 days ago | 12.17472794 FTM | ||||
87201217 | 70 days ago | 12.15338706 FTM | ||||
87201217 | 70 days ago | 4.88579913 FTM | ||||
87201217 | 70 days ago | 12.16777738 FTM | ||||
87201217 | 70 days ago | 12.20527504 FTM | ||||
87201217 | 70 days ago | 24.28200865 FTM | ||||
87201217 | 70 days ago | 18.23008059 FTM | ||||
87201217 | 70 days ago | 12.16777738 FTM | ||||
87201217 | 70 days ago | 12.20527504 FTM |
Loading...
Loading
Contract Name:
SFCLib
Compiler Version
v0.5.17+commit.d19bba13
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.0; import "../common/Decimal.sol"; import "./GasPriceConstants.sol"; import "./SFCBase.sol"; import "./StakeTokenizer.sol"; import "./NodeDriver.sol"; contract SFCLib is SFCBase { event CreatedValidator(uint256 indexed validatorID, address indexed auth, uint256 createdEpoch, uint256 createdTime); event Delegated(address indexed delegator, uint256 indexed toValidatorID, uint256 amount); event Undelegated(address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount); event Withdrawn(address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount); event ClaimedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward); event RestakedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward); event BurntFTM(uint256 amount); event LockedUpStake(address indexed delegator, uint256 indexed validatorID, uint256 duration, uint256 amount); event UnlockedStake(address indexed delegator, uint256 indexed validatorID, uint256 amount, uint256 penalty); event UpdatedSlashingRefundRatio(uint256 indexed validatorID, uint256 refundRatio); event RefundedSlashedLegacyDelegation(address indexed delegator, uint256 indexed validatorID, uint256 amount); /* Constructor */ function setGenesisValidator(address auth, uint256 validatorID, bytes calldata pubkey, uint256 status, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedEpoch, uint256 deactivatedTime) external onlyDriver { _rawCreateValidator(auth, validatorID, pubkey, status, createdEpoch, createdTime, deactivatedEpoch, deactivatedTime); if (validatorID > lastValidatorID) { lastValidatorID = validatorID; } } function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake, uint256 lockedStake, uint256 lockupFromEpoch, uint256 lockupEndTime, uint256 lockupDuration, uint256 earlyUnlockPenalty, uint256 rewards) external onlyDriver { _rawDelegate(delegator, toValidatorID, stake, false); _rewardsStash[delegator][toValidatorID].unlockedReward = rewards; _mintNativeToken(stake); if (lockedStake != 0) { require(lockedStake <= stake, "locked stake is greater than the whole stake"); LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID]; ld.lockedStake = lockedStake; ld.fromEpoch = lockupFromEpoch; ld.endTime = lockupEndTime; ld.duration = lockupDuration; getStashedLockupRewards[delegator][toValidatorID].lockupExtraReward = earlyUnlockPenalty; emit LockedUpStake(delegator, toValidatorID, lockupDuration, lockedStake); } } /* Methods */ function createValidator(bytes calldata pubkey) external payable { require(msg.value >= c.minSelfStake(), "insufficient self-stake"); require(pubkey.length == 66 && pubkey[0] == 0xc0, "malformed pubkey"); require(pubkeyHashToValidatorID[keccak256(pubkey)] == 0, "already used"); _createValidator(msg.sender, pubkey); _delegate(msg.sender, lastValidatorID, msg.value); } function _createValidator(address auth, bytes memory pubkey) internal { uint256 validatorID = ++lastValidatorID; _rawCreateValidator(auth, validatorID, pubkey, OK_STATUS, currentEpoch(), _now(), 0, 0); } function _rawCreateValidator(address auth, uint256 validatorID, bytes memory pubkey, uint256 status, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedEpoch, uint256 deactivatedTime) internal { require(getValidatorID[auth] == 0, "validator already exists"); getValidatorID[auth] = validatorID; getValidator[validatorID].status = status; getValidator[validatorID].createdEpoch = createdEpoch; getValidator[validatorID].createdTime = createdTime; getValidator[validatorID].deactivatedTime = deactivatedTime; getValidator[validatorID].deactivatedEpoch = deactivatedEpoch; getValidator[validatorID].auth = auth; getValidatorPubkey[validatorID] = pubkey; pubkeyHashToValidatorID[keccak256(pubkey)] = validatorID; emit CreatedValidator(validatorID, auth, createdEpoch, createdTime); if (deactivatedEpoch != 0) { emit DeactivatedValidator(validatorID, deactivatedEpoch, deactivatedTime); } if (status != 0) { emit ChangedValidatorStatus(validatorID, status); } } function getSelfStake(uint256 validatorID) public view returns (uint256) { return getStake[getValidator[validatorID].auth][validatorID]; } function _checkDelegatedStakeLimit(uint256 validatorID) internal view returns (bool) { return getValidator[validatorID].receivedStake <= getSelfStake(validatorID).mul(c.maxDelegatedRatio()).div(Decimal.unit()); } function delegate(uint256 toValidatorID) external payable { _delegate(msg.sender, toValidatorID, msg.value); } function _delegate(address delegator, uint256 toValidatorID, uint256 amount) internal { require(_validatorExists(toValidatorID), "validator doesn't exist"); require(getValidator[toValidatorID].status == OK_STATUS, "validator isn't active"); _rawDelegate(delegator, toValidatorID, amount, true); require(_checkDelegatedStakeLimit(toValidatorID), "validator's delegations limit is exceeded"); } function _rawDelegate(address delegator, uint256 toValidatorID, uint256 amount, bool strict) internal { require(amount > 0, "zero amount"); _stashRewards(delegator, toValidatorID); getStake[delegator][toValidatorID] = getStake[delegator][toValidatorID].add(amount); uint256 origStake = getValidator[toValidatorID].receivedStake; getValidator[toValidatorID].receivedStake = origStake.add(amount); totalStake = totalStake.add(amount); if (getValidator[toValidatorID].status == OK_STATUS) { totalActiveStake = totalActiveStake.add(amount); } _syncValidator(toValidatorID, origStake == 0); emit Delegated(delegator, toValidatorID, amount); _recountVotes(delegator, getValidator[toValidatorID].auth, strict); } function recountVotes(address delegator, address validatorAuth, bool strict, uint256 gas) external { (bool success,) = voteBookAddress.call.gas(gas)(abi.encodeWithSignature("recountVotes(address,address)", delegator, validatorAuth)); require(success || !strict, "gov votes recounting failed"); } function _rawUndelegate(address delegator, uint256 toValidatorID, uint256 amount, bool strict, bool forceful, bool checkDelegatedStake) internal { getStake[delegator][toValidatorID] -= amount; getValidator[toValidatorID].receivedStake = getValidator[toValidatorID].receivedStake.sub(amount); totalStake = totalStake.sub(amount); if (getValidator[toValidatorID].status == OK_STATUS) { totalActiveStake = totalActiveStake.sub(amount); } uint256 selfStakeAfterwards = getSelfStake(toValidatorID); if (selfStakeAfterwards != 0 && getValidator[toValidatorID].status == OK_STATUS) { if (!(selfStakeAfterwards >= c.minSelfStake())) { if (forceful) { revert("insufficient self-stake"); } else { _setValidatorDeactivated(toValidatorID, WITHDRAWN_BIT); } } require(!checkDelegatedStake || _checkDelegatedStakeLimit(toValidatorID), "validator's delegations limit is exceeded"); } else { _setValidatorDeactivated(toValidatorID, WITHDRAWN_BIT); } _recountVotes(delegator, getValidator[toValidatorID].auth, strict); } function undelegate(uint256 toValidatorID, uint256 wrID, uint256 amount) public { address delegator = msg.sender; _stashRewards(delegator, toValidatorID); require(amount > 0, "zero amount"); require(amount <= getUnlockedStake(delegator, toValidatorID), "not enough unlocked stake"); require(_checkAllowedToWithdraw(delegator, toValidatorID), "outstanding sFTM balance"); require(getWithdrawalRequest[delegator][toValidatorID][wrID].amount == 0, "wrID already exists"); _rawUndelegate(delegator, toValidatorID, amount, true, false, true); getWithdrawalRequest[delegator][toValidatorID][wrID].amount = amount; getWithdrawalRequest[delegator][toValidatorID][wrID].epoch = currentEpoch(); getWithdrawalRequest[delegator][toValidatorID][wrID].time = _now(); _syncValidator(toValidatorID, false); emit Undelegated(delegator, toValidatorID, wrID, amount); } // liquidateSFTM is used for finalization of last fMint positions with outstanding sFTM balances // it allows to undelegate without the unboding period, and also to unlock stake without a penalty. // Such a simplification, which might be dangerous generally, is okay here because there's only a small amount // of leftover sFTM function liquidateSFTM(address delegator, uint256 toValidatorID, uint256 amount) external { require(msg.sender == sftmFinalizer, "not sFTM finalizer"); _stashRewards(delegator, toValidatorID); require(amount > 0, "zero amount"); StakeTokenizer(stakeTokenizerAddress).redeemSFTMFor(msg.sender, delegator, toValidatorID, amount); require(amount <= getStake[delegator][toValidatorID], "not enough stake"); uint256 unlockedStake = getUnlockedStake(delegator, toValidatorID); if (amount > unlockedStake) { LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID]; ld.lockedStake = ld.lockedStake.sub(amount - unlockedStake); emit UnlockedStake(delegator, toValidatorID, amount - unlockedStake, 0); } _rawUndelegate(delegator, toValidatorID, amount, false, true, false); _syncValidator(toValidatorID, false); emit Undelegated(delegator, toValidatorID, 0xffffffffff, amount); // It's important that we transfer after erasing (protection against Re-Entrancy) (bool sent,) = msg.sender.call.value(amount)(""); require(sent, "Failed to send FTM"); emit Withdrawn(delegator, toValidatorID, 0xffffffffff, amount); } function isSlashed(uint256 validatorID) view public returns (bool) { return getValidator[validatorID].status & CHEATER_MASK != 0; } function getSlashingPenalty(uint256 amount, bool isCheater, uint256 refundRatio) internal pure returns (uint256 penalty) { if (!isCheater || refundRatio >= Decimal.unit()) { return 0; } // round penalty upwards (ceiling) to prevent dust amount attacks penalty = amount.mul(Decimal.unit() - refundRatio).div(Decimal.unit()).add(1); if (penalty > amount) { return amount; } return penalty; } function _withdraw(address payable delegator, uint256 toValidatorID, uint256 wrID, address payable receiver) private { WithdrawalRequest memory request = getWithdrawalRequest[delegator][toValidatorID][wrID]; require(request.epoch != 0, "request doesn't exist"); require(_checkAllowedToWithdraw(delegator, toValidatorID), "outstanding sFTM balance"); uint256 requestTime = request.time; uint256 requestEpoch = request.epoch; if (getValidator[toValidatorID].deactivatedTime != 0 && getValidator[toValidatorID].deactivatedTime < requestTime) { requestTime = getValidator[toValidatorID].deactivatedTime; requestEpoch = getValidator[toValidatorID].deactivatedEpoch; } require(_now() >= requestTime + c.withdrawalPeriodTime(), "not enough time passed"); require(currentEpoch() >= requestEpoch + c.withdrawalPeriodEpochs(), "not enough epochs passed"); uint256 amount = getWithdrawalRequest[delegator][toValidatorID][wrID].amount; bool isCheater = isSlashed(toValidatorID); uint256 penalty = getSlashingPenalty(amount, isCheater, slashingRefundRatio[toValidatorID]); delete getWithdrawalRequest[delegator][toValidatorID][wrID]; totalSlashedStake += penalty; require(amount > penalty, "stake is fully slashed"); // It's important that we transfer after erasing (protection against Re-Entrancy) (bool sent,) = receiver.call.value(amount.sub(penalty))(""); require(sent, "Failed to send FTM"); _burnFTM(penalty); emit Withdrawn(delegator, toValidatorID, wrID, amount); } function withdraw(uint256 toValidatorID, uint256 wrID) public { _withdraw(msg.sender, toValidatorID, wrID, _receiverOf(msg.sender)); } function deactivateValidator(uint256 validatorID, uint256 status) external onlyDriver { require(status != OK_STATUS, "wrong status"); _setValidatorDeactivated(validatorID, status); _syncValidator(validatorID, false); address validatorAddr = getValidator[validatorID].auth; _recountVotes(validatorAddr, validatorAddr, false); } function _highestPayableEpoch(uint256 validatorID) internal view returns (uint256) { if (getValidator[validatorID].deactivatedEpoch != 0) { if (currentSealedEpoch < getValidator[validatorID].deactivatedEpoch) { return currentSealedEpoch; } return getValidator[validatorID].deactivatedEpoch; } return currentSealedEpoch; } // find highest epoch such that _isLockedUpAtEpoch returns true (using binary search) function _highestLockupEpoch(address delegator, uint256 validatorID) internal view returns (uint256) { uint256 l = getLockupInfo[delegator][validatorID].fromEpoch; uint256 r = currentSealedEpoch; if (_isLockedUpAtEpoch(delegator, validatorID, r)) { return r; } if (!_isLockedUpAtEpoch(delegator, validatorID, l)) { return 0; } if (l > r) { return 0; } while (l < r) { uint256 m = (l + r) / 2; if (_isLockedUpAtEpoch(delegator, validatorID, m)) { l = m + 1; } else { r = m; } } if (r == 0) { return 0; } return r - 1; } function _newRewards(address delegator, uint256 toValidatorID) internal view returns (Rewards memory) { uint256 stashedUntil = stashedRewardsUntilEpoch[delegator][toValidatorID]; uint256 payableUntil = _highestPayableEpoch(toValidatorID); uint256 lockedUntil = _highestLockupEpoch(delegator, toValidatorID); if (lockedUntil > payableUntil) { lockedUntil = payableUntil; } if (lockedUntil < stashedUntil) { lockedUntil = stashedUntil; } LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID]; uint256 wholeStake = getStake[delegator][toValidatorID]; uint256 unlockedStake = wholeStake.sub(ld.lockedStake); uint256 fullReward; // count reward for locked stake during lockup epochs fullReward = _newRewardsOf(ld.lockedStake, toValidatorID, stashedUntil, lockedUntil); Rewards memory plReward = _scaleLockupReward(fullReward, ld.duration); // count reward for unlocked stake during lockup epochs fullReward = _newRewardsOf(unlockedStake, toValidatorID, stashedUntil, lockedUntil); Rewards memory puReward = _scaleLockupReward(fullReward, 0); // count lockup reward for unlocked stake during unlocked epochs fullReward = _newRewardsOf(wholeStake, toValidatorID, lockedUntil, payableUntil); Rewards memory wuReward = _scaleLockupReward(fullReward, 0); return sumRewards(plReward, puReward, wuReward); } function _newRewardsOf(uint256 stakeAmount, uint256 toValidatorID, uint256 fromEpoch, uint256 toEpoch) internal view returns (uint256) { if (fromEpoch >= toEpoch) { return 0; } uint256 stashedRate = getEpochSnapshot[fromEpoch].accumulatedRewardPerToken[toValidatorID]; uint256 currentRate = getEpochSnapshot[toEpoch].accumulatedRewardPerToken[toValidatorID]; return currentRate.sub(stashedRate).mul(stakeAmount).div(Decimal.unit()); } function _pendingRewards(address delegator, uint256 toValidatorID) internal view returns (Rewards memory) { Rewards memory reward = _newRewards(delegator, toValidatorID); return sumRewards(_rewardsStash[delegator][toValidatorID], reward); } function pendingRewards(address delegator, uint256 toValidatorID) public view returns (uint256) { Rewards memory reward = _pendingRewards(delegator, toValidatorID); return reward.unlockedReward.add(reward.lockupBaseReward).add(reward.lockupExtraReward); } function stashRewards(address delegator, uint256 toValidatorID) external { require(_stashRewards(delegator, toValidatorID), "nothing to stash"); } function _stashRewards(address delegator, uint256 toValidatorID) internal returns (bool updated) { Rewards memory nonStashedReward = _newRewards(delegator, toValidatorID); stashedRewardsUntilEpoch[delegator][toValidatorID] = _highestPayableEpoch(toValidatorID); _rewardsStash[delegator][toValidatorID] = sumRewards(_rewardsStash[delegator][toValidatorID], nonStashedReward); getStashedLockupRewards[delegator][toValidatorID] = sumRewards(getStashedLockupRewards[delegator][toValidatorID], nonStashedReward); if (!isLockedUp(delegator, toValidatorID)) { delete getLockupInfo[delegator][toValidatorID]; delete getStashedLockupRewards[delegator][toValidatorID]; } _truncateLegacyPenalty(delegator, toValidatorID); return nonStashedReward.lockupBaseReward != 0 || nonStashedReward.lockupExtraReward != 0 || nonStashedReward.unlockedReward != 0; } function _claimRewards(address delegator, uint256 toValidatorID) internal returns (Rewards memory rewards) { require(_checkAllowedToWithdraw(delegator, toValidatorID), "outstanding sFTM balance"); _stashRewards(delegator, toValidatorID); rewards = _rewardsStash[delegator][toValidatorID]; uint256 totalReward = rewards.unlockedReward.add(rewards.lockupBaseReward).add(rewards.lockupExtraReward); require(totalReward != 0, "zero rewards"); delete _rewardsStash[delegator][toValidatorID]; // It's important that we mint after erasing (protection against Re-Entrancy) _mintNativeToken(totalReward); return rewards; } function claimRewards(uint256 toValidatorID) public { address payable delegator = msg.sender; Rewards memory rewards = _claimRewards(delegator, toValidatorID); // It's important that we transfer after erasing (protection against Re-Entrancy) (bool sent,) = _receiverOf(delegator).call.value(rewards.lockupExtraReward.add(rewards.lockupBaseReward).add(rewards.unlockedReward))(""); require(sent, "Failed to send FTM"); emit ClaimedRewards(delegator, toValidatorID, rewards.lockupExtraReward, rewards.lockupBaseReward, rewards.unlockedReward); } function restakeRewards(uint256 toValidatorID) public { address delegator = msg.sender; Rewards memory rewards = _claimRewards(delegator, toValidatorID); uint256 lockupReward = rewards.lockupExtraReward.add(rewards.lockupBaseReward); _delegate(delegator, toValidatorID, lockupReward.add(rewards.unlockedReward)); getLockupInfo[delegator][toValidatorID].lockedStake += lockupReward; emit RestakedRewards(delegator, toValidatorID, rewards.lockupExtraReward, rewards.lockupBaseReward, rewards.unlockedReward); } // burnFTM allows SFC to burn an arbitrary amount of FTM tokens function burnFTM(uint256 amount) onlyOwner external { _burnFTM(amount); } function _burnFTM(uint256 amount) internal { if (amount != 0) { address(0).transfer(amount); emit BurntFTM(amount); } } function epochEndTime(uint256 epoch) view internal returns (uint256) { return getEpochSnapshot[epoch].endTime; } function _isLockedUpAtEpoch(address delegator, uint256 toValidatorID, uint256 epoch) internal view returns (bool) { return getLockupInfo[delegator][toValidatorID].fromEpoch <= epoch && epochEndTime(epoch) <= getLockupInfo[delegator][toValidatorID].endTime; } function _checkAllowedToWithdraw(address delegator, uint256 toValidatorID) internal view returns (bool) { if (stakeTokenizerAddress == address(0)) { return true; } return StakeTokenizer(stakeTokenizerAddress).allowedToWithdrawStake(delegator, toValidatorID); } function getUnlockedStake(address delegator, uint256 toValidatorID) public view returns (uint256) { if (!isLockedUp(delegator, toValidatorID)) { return getStake[delegator][toValidatorID]; } return getStake[delegator][toValidatorID].sub(getLockupInfo[delegator][toValidatorID].lockedStake); } function _lockStake(address delegator, uint256 toValidatorID, uint256 lockupDuration, uint256 amount, bool relock) internal { require(!_redirected(delegator), "redirected"); require(amount <= getUnlockedStake(delegator, toValidatorID), "not enough stake"); require(getValidator[toValidatorID].status == OK_STATUS, "validator isn't active"); require(lockupDuration >= c.minLockupDuration() && lockupDuration <= c.maxLockupDuration(), "incorrect duration"); uint256 endTime = _now().add(lockupDuration); address validatorAddr = getValidator[toValidatorID].auth; if (delegator != validatorAddr) { require(getLockupInfo[validatorAddr][toValidatorID].endTime + 30 * 24 * 60 * 60 >= endTime, "validator's lockup will end too early"); } _stashRewards(delegator, toValidatorID); _delStalePenalties(delegator, toValidatorID); // stash the previous penalty and clean getStashedLockupRewards LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID]; if (relock) { Penalty[] storage penalties = getStashedPenalties[delegator][toValidatorID]; uint256 penalty = _popNonStashedUnlockPenalty(delegator, toValidatorID, ld.lockedStake, ld.lockedStake); if (penalty != 0) { penalties.push(Penalty(penalty, ld.endTime)); require(penalties.length <= 30, "too many ongoing relocks"); require(amount > ld.lockedStake / 100 || penalties.length <= 3 || endTime >= ld.endTime + 14 * 24 * 60 * 60, "too frequent relocks (github.com/Fantom-foundation/opera-sfc/wiki/Lockup-calls-reference#re-lock-stake)"); } } // check lockup duration after _stashRewards, which has erased previous lockup if it has unlocked already require(lockupDuration >= ld.duration, "lockup duration cannot decrease"); ld.lockedStake = ld.lockedStake.add(amount); ld.fromEpoch = currentEpoch(); ld.endTime = endTime; ld.duration = lockupDuration; emit LockedUpStake(delegator, toValidatorID, lockupDuration, amount); } function lockStake(uint256 toValidatorID, uint256 lockupDuration, uint256 amount) public { address delegator = msg.sender; require(amount > 0, "zero amount"); require(!isLockedUp(delegator, toValidatorID), "already locked up"); _lockStake(delegator, toValidatorID, lockupDuration, amount, false); } function relockStake(uint256 toValidatorID, uint256 lockupDuration, uint256 amount) public { address delegator = msg.sender; require(isLockedUp(delegator, toValidatorID), "not locked up"); _lockStake(delegator, toValidatorID, lockupDuration, amount, true); } function _popNonStashedUnlockPenalty(address delegator, uint256 toValidatorID, uint256 unlockAmount, uint256 totalAmount) internal returns (uint256) { Rewards storage r = getStashedLockupRewards[delegator][toValidatorID]; uint256 lockupExtraRewardShare = r.lockupExtraReward.mul(unlockAmount).div(totalAmount); uint256 lockupBaseRewardShare = r.lockupBaseReward.mul(unlockAmount).div(totalAmount); uint256 penalty = lockupExtraRewardShare + lockupBaseRewardShare / 2; r.lockupExtraReward = r.lockupExtraReward.sub(lockupExtraRewardShare); r.lockupBaseReward = r.lockupBaseReward.sub(lockupBaseRewardShare); return penalty; } function _popStashedUnlockPenalty(address delegator, uint256 toValidatorID, uint256 unlockAmount, uint256 totalAmount) internal returns (uint256) { _delStalePenalties(delegator, toValidatorID); Penalty[] storage penalties = getStashedPenalties[delegator][toValidatorID]; uint256 total = 0; for (uint256 i = 0; i < penalties.length; i++) { uint256 penalty = penalties[i].amount.mul(unlockAmount).div(totalAmount); penalties[i].amount = penalties[i].amount.sub(penalty); total = total.add(penalty); } return total; } function _popWholeUnlockPenalty(address delegator, uint256 toValidatorID, uint256 unlockAmount, uint256 totalAmount) internal returns (uint256) { uint256 nonStashed = _popNonStashedUnlockPenalty(delegator, toValidatorID, unlockAmount, totalAmount); uint256 stashed = _popStashedUnlockPenalty(delegator, toValidatorID, unlockAmount, totalAmount); return nonStashed + stashed; } function unlockStake(uint256 toValidatorID, uint256 amount) external returns (uint256) { address delegator = msg.sender; LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID]; require(amount > 0, "zero amount"); require(isLockedUp(delegator, toValidatorID), "not locked up"); require(amount <= ld.lockedStake, "not enough locked stake"); require(_checkAllowedToWithdraw(delegator, toValidatorID), "outstanding sFTM balance"); require(!_redirected(delegator), "redirected"); _stashRewards(delegator, toValidatorID); uint256 penalty = _popWholeUnlockPenalty(delegator, toValidatorID, amount, ld.lockedStake); if (penalty > amount) { penalty = amount; } ld.lockedStake -= amount; if (penalty != 0) { _rawUndelegate(delegator, toValidatorID, penalty, true, false, false); treasuryAddress.call.value(penalty)(""); } emit UnlockedStake(delegator, toValidatorID, amount, penalty); return penalty; } function updateSlashingRefundRatio(uint256 validatorID, uint256 refundRatio) onlyOwner external { require(isSlashed(validatorID), "validator isn't slashed"); require(refundRatio <= Decimal.unit(), "must be less than or equal to 1.0"); slashingRefundRatio[validatorID] = refundRatio; emit UpdatedSlashingRefundRatio(validatorID, refundRatio); } function _delStalePenalties(address delegator, uint256 toValidatorID) public { Penalty[] storage penalties = getStashedPenalties[delegator][toValidatorID]; for (uint256 i = 0; i < penalties.length;) { if (penalties[i].end < _now() || penalties[i].amount == 0) { penalties[i] = penalties[penalties.length - 1]; penalties.pop(); } else { i++; } } } function redirectedAccs() private pure returns(address[] memory, address[] memory) { // the addresses below were reported as stolen by their owners via the signatures below: // I redirect SFC withdrawals to account 0x80f93310709624636852d0111fd6c4A6e02ED0aA due to a potential attacker gaining access to my account. // { // "address": "0x93419fcb5d9dc7989439f0512d4f737421ed48d9", // "msg": "0x4920726564697265637420534643207769746864726177616c7320746f206163636f756e74203078383066393333313037303936323436333638353264303131316664366334413665303245443061412064756520746f206120706f74656e7469616c2061747461636b6572206761696e696e672061636365737320746f206d79206163636f756e742e", // "sig": "1c4f3168e01d499a657f0d1cd453b26e5f69aaf14372983ff62e54a1d53959e55edb0746f4aea0959899b06bf31dc6a0160f6ac428cd75d4657184ab2337e46e1c", // "version": "3", // "signer": "MEW" // } // -- // I redirect SFC withdrawals to account 0x91B20102Dfd2ff1b00D0915266584009d0b1Ae39 due to a potential attacker gaining access to my account. // { // "address": "0xfbcae1b28ca5039dafec4f10a89e022bc8118394", // "msg": "0x4920726564697265637420534643207769746864726177616c7320746f206163636f756e74203078393142323031303244666432666631623030443039313532363635383430303964306231416533392064756520746f206120706f74656e7469616c2061747461636b6572206761696e696e672061636365737320746f206d79206163636f756e742e", // "sig": "c98431cc1b6f26b8248ca83f860721f31ec79097831e69c28d352512182bbfa93911564ed46ba11547b544c4d65380781a4f3cc6afe9f075d43a24e0947853151c", // "version": "3", // "signer": "MEW" // } // -- // I redirect SFC withdrawals to account 0xCA3C54c11172A7263300a801E9937780b5143c08 due to a potential attacker gaining access to my account. // { // "address": "0x15c2ec517905fb3282f26f3ac3e12889755a2ed7", // "msg": "0x4920726564697265637420534643207769746864726177616c7320746f206163636f756e74203078434133433534633131313732413732363333303061383031453939333737383062353134336330382064756520746f206120706f74656e7469616c2061747461636b6572206761696e696e672061636365737320746f206d79206163636f756e742e", // "sig": "8d933ea6b1dfaa70c92d7dd8f68e9c821934eabd9c454dc792a90c9c58d0c4ec5c60d7737e7b8ed38cfdfe3bd7fce9a2c38133b9a98d6699088d79edb09ec3c21b", // "version": "3", // "signer": "MEW" // } // -- // I redirect SFC withdrawals to account 0x5A1CAd027EACE4C052f5DEE0f42Da6c62E39b779 due to a potential attacker gaining access to my account. // { // "address": "0xbdAaEC5f9317cC63D26FD7d79aD17372Ccd7d763", // "msg": "0x4920726564697265637420534643207769746864726177616c7320746f206163636f756e74203078354131434164303237454143453443303532663544454530663432446136633632453339623737392064756520746f206120706f74656e7469616c2061747461636b6572206761696e696e672061636365737320746f206d79206163636f756e742e", // "sig": "0e9b3ce37f665ab03bdfd3095671249e1b2842b1dd314fd4281bbed527ea69014ca510227e57f973b35ef175c1214fb1a842be70ff5a9290cb260799c544eed900", // "version": "3", // "signer": "MEW" // } // -- // I redirect SFC withdrawals to account 0x4A15B527475977D9B0CB3fcfE825d6Aa7428fAFC due to a potential attacker gaining access to my account. // { // "address": "0xf72148504819A1D1B038694B02d299F65BfA312d", // "msg": "0x4920726564697265637420534643207769746864726177616c7320746f206163636f756e74203078344131354235323734373539373744394230434233666366453832356436416137343238664146432064756520746f206120706f74656e7469616c2061747461636b6572206761696e696e672061636365737320746f206d79206163636f756e742e", // "sig": "cf6386edbbee504c07ae95cb7c5ef06e7e0f57b34d51ab4e4047b5cb326af9bc236f544a3ced994cd20601047966e683aaaf329772fbb6bf37f0bd12200d1e6100", // "version": "3", // "signer": "MEW" // } // The contract does not lock these positions; instead, it restricts withdrawals exclusively to the account designated in the signature. // This measure prevents an attacker from transferring FTM following a withdrawal. address[] memory froms = new address[](5); address[] memory tos = new address[](5); assert(froms.length == tos.length); froms[0] = 0x93419FcB5d9DC7989439f0512d4F737421ed48D9; tos[0] = 0x80f93310709624636852d0111fd6c4A6e02ED0aA; froms[1] = 0xFbCAe1B28ca5039DAFec4f10A89e022Bc8118394; tos[1] = 0x91B20102Dfd2ff1b00D0915266584009d0b1Ae39; froms[2] = 0x15C2EC517905fB3282f26F3aC3e12889755a2ed7; tos[2] = 0xCA3C54c11172A7263300a801E9937780b5143c08; froms[3] = 0xbdAaEC5f9317cC63D26FD7d79aD17372Ccd7d763; tos[3] = 0x5A1CAd027EACE4C052f5DEE0f42Da6c62E39b779; froms[4] = 0xf72148504819A1D1B038694B02d299F65BfA312d; tos[4] = 0x4A15B527475977D9B0CB3fcfE825d6Aa7428fAFC; return (froms, tos); } function _redirected(address addr) internal view returns(bool) { (address[] memory froms,) = redirectedAccs(); for (uint256 i = 0; i < froms.length; i++) { if (addr == froms[i]) { return true; } } return getRedirection[addr] != address(0); } function _redirectedTo(address addr) internal view returns(address) { (address[] memory froms, address[] memory tos) = redirectedAccs(); for (uint256 i = 0; i < froms.length; i++) { if (addr == froms[i]) { return tos[i]; } } return getRedirection[addr]; } function _receiverOf(address addr) internal view returns(address payable) { address to = _redirectedTo(addr); if (to == address(0)) { return address(uint160(addr)); } return address(uint160(to)); } // code below can be erased after 1 year since deployment of multipenalties function _getAvgEpochStep(uint256 duration) internal view returns(uint256) { // estimate number of epochs such that we would make approximately 15 iterations uint256 tryEpochs = currentSealedEpoch / 5; if (tryEpochs > 10000) { tryEpochs = 10000; } uint256 tryEndTime = getEpochSnapshot[currentSealedEpoch - tryEpochs].endTime; if (tryEndTime == 0 || tryEpochs == 0) { return 0; } uint256 secondsPerEpoch = _now().sub(tryEndTime) / tryEpochs; return duration / (secondsPerEpoch * 15 + 1); } function _getAvgReceivedStake(uint256 validatorID, uint256 duration, uint256 step) internal view returns(uint256) { uint256 receivedStakeSum = getValidator[validatorID].receivedStake; uint256 samples = 1; uint256 until = _now().sub(duration); for (uint256 i = 1; i <= 30; i++) { uint256 e = currentSealedEpoch - i * step; EpochSnapshot storage s = getEpochSnapshot[e]; if (s.endTime < until) { break; } uint256 sample = s.receivedStake[validatorID]; if (sample != 0) { samples++; receivedStakeSum += sample; } } return receivedStakeSum / samples; } function _getAvgUptime(uint256 validatorID, uint256 duration, uint256 step) internal view returns(uint256) { uint256 until = _now().sub(duration); uint256 oldUptimeCounter = 0; uint256 newUptimeCounter = 0; for (uint256 i = 0; i <= 30; i++) { uint256 e = currentSealedEpoch - i * step; EpochSnapshot storage s = getEpochSnapshot[e]; uint256 endTime = s.endTime; if (endTime < until) { if (i <= 2) { return duration; } break; } uint256 uptimeCounter = s.accumulatedUptime[validatorID]; if (uptimeCounter != 0) { oldUptimeCounter = uptimeCounter; if (newUptimeCounter == 0) { newUptimeCounter = uptimeCounter; } } } uint256 uptime = newUptimeCounter - oldUptimeCounter; if (uptime > duration*4/5) { return duration; } return uptime; } function _truncateLegacyPenalty(address delegator, uint256 toValidatorID) internal { Rewards storage r = getStashedLockupRewards[delegator][toValidatorID]; uint256 storedPenalty = r.lockupExtraReward + r.lockupBaseReward / 2; if (storedPenalty == 0) { return; } LockedDelegation storage ld = getLockupInfo[delegator][toValidatorID]; uint256 duration = ld.duration; uint256 lockedStake = ld.lockedStake; uint256 step = _getAvgEpochStep(duration); if (step == 0) { return; } uint256 RPS = _getAvgUptime(toValidatorID, duration, step).mul(2092846271).div(duration); // corresponds to 6.6% APR uint256 selfStake = getStake[delegator][toValidatorID]; uint256 avgFullReward = selfStake.mul(RPS).mul(duration).div(1e18).mul(Decimal.unit().sub(c.validatorCommission())).div(Decimal.unit()); // reward for self-stake if (getValidator[toValidatorID].auth == delegator) { // reward for received portion of stake uint256 receivedStakeAvg = _getAvgReceivedStake(toValidatorID, duration, step).mul(11).div(10); avgFullReward += receivedStakeAvg.mul(RPS).mul(duration).div(1e18).mul(c.validatorCommission()).div(Decimal.unit()); } avgFullReward = avgFullReward.mul(lockedStake).div(selfStake); Rewards memory avgReward = _scaleLockupReward(avgFullReward, duration); uint256 maxReasonablePenalty = avgReward.lockupBaseReward / 2 + avgReward.lockupExtraReward; maxReasonablePenalty = maxReasonablePenalty; if (storedPenalty > maxReasonablePenalty) { r.lockupExtraReward = r.lockupExtraReward.mul(maxReasonablePenalty).div(storedPenalty); r.lockupBaseReward = r.lockupBaseReward.mul(maxReasonablePenalty).div(storedPenalty); } } }
pragma solidity ^0.5.0; library Decimal { // unit is used for decimals, e.g. 0.123456 function unit() internal pure returns (uint256) { return 1e18; } }
pragma solidity ^0.5.0; import "../common/Decimal.sol"; library GP { function trimGasPriceChangeRatio(uint256 x) internal pure returns (uint256) { if (x > Decimal.unit() * 105 / 100) { return Decimal.unit() * 105 / 100; } if (x < Decimal.unit() * 95 / 100) { return Decimal.unit() * 95 / 100; } return x; } function trimMinGasPrice(uint256 x) internal pure returns (uint256) { if (x > 1000000 * 1e9) { return 1000000 * 1e9; } if (x < 1e9) { return 1e9; } return x; } function initialMinGasPrice() internal pure returns (uint256) { return 100 * 1e9; } }
pragma solidity ^0.5.0; import "./SFCState.sol"; contract SFCBase is SFCState { using SafeMath for uint256; uint256 internal constant OK_STATUS = 0; uint256 internal constant WITHDRAWN_BIT = 1; uint256 internal constant OFFLINE_BIT = 1 << 3; uint256 internal constant DOUBLESIGN_BIT = 1 << 7; uint256 internal constant CHEATER_MASK = DOUBLESIGN_BIT; event DeactivatedValidator(uint256 indexed validatorID, uint256 deactivatedEpoch, uint256 deactivatedTime); event ChangedValidatorStatus(uint256 indexed validatorID, uint256 status); function isNode(address addr) internal view returns (bool) { return addr == address(node); } modifier onlyDriver() { require(isNode(msg.sender), "caller is not the NodeDriverAuth contract"); _; } function currentEpoch() public view returns (uint256) { return currentSealedEpoch + 1; } function _calcRawValidatorEpochTxReward(uint256 epochFee, uint256 txRewardWeight, uint256 totalTxRewardWeight) internal view returns (uint256) { if (txRewardWeight == 0) { return 0; } uint256 txReward = epochFee.mul(txRewardWeight).div(totalTxRewardWeight); // fee reward except burntFeeShare and treasuryFeeShare return txReward.mul(Decimal.unit() - c.burntFeeShare() - c.treasuryFeeShare()).div(Decimal.unit()); } function _calcRawValidatorEpochBaseReward(uint256 epochDuration, uint256 _baseRewardPerSecond, uint256 baseRewardWeight, uint256 totalBaseRewardWeight) internal pure returns (uint256) { if (baseRewardWeight == 0) { return 0; } uint256 totalReward = epochDuration.mul(_baseRewardPerSecond); return totalReward.mul(baseRewardWeight).div(totalBaseRewardWeight); } function _mintNativeToken(uint256 amount) internal { // balance will be increased after the transaction is processed node.incBalance(address(this), amount); totalSupply = totalSupply.add(amount); } function sumRewards(Rewards memory a, Rewards memory b) internal pure returns (Rewards memory) { return Rewards(a.lockupExtraReward.add(b.lockupExtraReward), a.lockupBaseReward.add(b.lockupBaseReward), a.unlockedReward.add(b.unlockedReward)); } function sumRewards(Rewards memory a, Rewards memory b, Rewards memory c) internal pure returns (Rewards memory) { return sumRewards(sumRewards(a, b), c); } function _scaleLockupReward(uint256 fullReward, uint256 lockupDuration) internal view returns (Rewards memory reward) { reward = Rewards(0, 0, 0); uint256 unlockedRewardRatio = c.unlockedRewardRatio(); if (lockupDuration != 0) { uint256 maxLockupExtraRatio = Decimal.unit() - unlockedRewardRatio; uint256 lockupExtraRatio = maxLockupExtraRatio.mul(lockupDuration).div(c.maxLockupDuration()); uint256 totalScaledReward = fullReward.mul(unlockedRewardRatio + lockupExtraRatio).div(Decimal.unit()); reward.lockupBaseReward = fullReward.mul(unlockedRewardRatio).div(Decimal.unit()); reward.lockupExtraReward = totalScaledReward - reward.lockupBaseReward; } else { reward.unlockedReward = fullReward.mul(unlockedRewardRatio).div(Decimal.unit()); } return reward; } function _recountVotes(address delegator, address validatorAuth, bool strict) internal { if (voteBookAddress != address(0)) { // Don't allow recountVotes to use up all the gas (bool success,) = voteBookAddress.call.gas(8000000)(abi.encodeWithSignature("recountVotes(address,address)", delegator, validatorAuth)); // Don't revert if recountVotes failed unless strict mode enabled require(success || !strict, "gov votes recounting failed"); } } function _setValidatorDeactivated(uint256 validatorID, uint256 status) internal { if (getValidator[validatorID].status == OK_STATUS && status != OK_STATUS) { totalActiveStake = totalActiveStake.sub(getValidator[validatorID].receivedStake); } // status as a number is proportional to severity if (status > getValidator[validatorID].status) { getValidator[validatorID].status = status; if (getValidator[validatorID].deactivatedEpoch == 0) { getValidator[validatorID].deactivatedEpoch = currentEpoch(); getValidator[validatorID].deactivatedTime = _now(); emit DeactivatedValidator(validatorID, getValidator[validatorID].deactivatedEpoch, getValidator[validatorID].deactivatedTime); } emit ChangedValidatorStatus(validatorID, status); } } function _syncValidator(uint256 validatorID, bool syncPubkey) public { require(_validatorExists(validatorID), "validator doesn't exist"); // emit special log for node uint256 weight = getValidator[validatorID].receivedStake; if (getValidator[validatorID].status != OK_STATUS) { weight = 0; } node.updateValidatorWeight(validatorID, weight); if (syncPubkey && weight != 0) { node.updateValidatorPubkey(validatorID, getValidatorPubkey[validatorID]); } } function _validatorExists(uint256 validatorID) view internal returns (bool) { return getValidator[validatorID].createdTime != 0; } function _calcValidatorCommission(uint256 rawReward, uint256 commission) internal pure returns (uint256) { return rawReward.mul(commission).div(Decimal.unit()); } function getLockedStake(address delegator, uint256 toValidatorID) public view returns (uint256) { if (!isLockedUp(delegator, toValidatorID)) { return 0; } return getLockupInfo[delegator][toValidatorID].lockedStake; } function isLockedUp(address delegator, uint256 toValidatorID) view public returns (bool) { return getLockupInfo[delegator][toValidatorID].endTime != 0 && getLockupInfo[delegator][toValidatorID].lockedStake != 0 && _now() <= getLockupInfo[delegator][toValidatorID].endTime; } function _now() internal view returns (uint256) { return block.timestamp; } }
pragma solidity ^0.5.0; import "./SFC.sol"; import "../erc20/base/ERC20Burnable.sol"; import "../erc20/base/ERC20Mintable.sol"; import "../common/Initializable.sol"; contract Spacer { address private _owner; } contract StakeTokenizer is Spacer, Initializable { SFC internal sfc; mapping(address => mapping(uint256 => uint256)) public outstandingSFTM; address public sFTMTokenAddress; function initialize(address payable _sfc, address _sFTMTokenAddress) public initializer { sfc = SFC(_sfc); sFTMTokenAddress = _sFTMTokenAddress; } function mintSFTM(uint256 toValidatorID) external { revert("sFTM minting is disabled"); // address delegator = msg.sender; // uint256 lockedStake = sfc.getLockedStake(delegator, toValidatorID); // require(lockedStake > 0, "delegation isn't locked up"); // require(lockedStake > outstandingSFTM[delegator][toValidatorID], "sFTM is already minted"); // // uint256 diff = lockedStake - outstandingSFTM[delegator][toValidatorID]; // outstandingSFTM[delegator][toValidatorID] = lockedStake; // // // It's important that we mint after updating outstandingSFTM (protection against Re-Entrancy) // require(ERC20Mintable(sFTMTokenAddress).mint(delegator, diff), "failed to mint sFTM"); } function redeemSFTM(uint256 validatorID, uint256 amount) external { require(outstandingSFTM[msg.sender][validatorID] >= amount, "low outstanding sFTM balance"); require(IERC20(sFTMTokenAddress).allowance(msg.sender, address(this)) >= amount, "insufficient allowance"); outstandingSFTM[msg.sender][validatorID] -= amount; // It's important that we burn after updating outstandingSFTM (protection against Re-Entrancy) ERC20Burnable(sFTMTokenAddress).burnFrom(msg.sender, amount); } function redeemSFTMFor(address payer, address delegator, uint256 validatorID, uint256 amount) external { require(msg.sender == address(sfc), "not SFC"); require(outstandingSFTM[delegator][validatorID] >= amount, "low outstanding sFTM balance"); require(IERC20(sFTMTokenAddress).allowance(payer, address(this)) >= amount, "insufficient allowance"); outstandingSFTM[delegator][validatorID] -= amount; // It's important that we burn after updating outstandingSFTM (protection against Re-Entrancy) ERC20Burnable(sFTMTokenAddress).burnFrom(payer, amount); } function allowedToWithdrawStake(address sender, uint256 validatorID) public view returns(bool) { return outstandingSFTM[sender][validatorID] == 0; } }
pragma solidity ^0.5.0; import "../common/SafeMath.sol"; import "../common/Initializable.sol"; import "../ownership/Ownable.sol"; import "./SFCI.sol"; interface NodeDriverExecutable { function execute() external; } contract NodeDriverAuth is Initializable, Ownable { using SafeMath for uint256; SFCI internal sfc; NodeDriver internal driver; // Initialize NodeDriverAuth, NodeDriver and SFC in one call to allow fewer genesis transactions function initialize(address payable _sfc, address _driver, address _owner) external initializer { Ownable.initialize(_owner); driver = NodeDriver(_driver); sfc = SFCI(_sfc); } modifier onlySFC() { require(msg.sender == address(sfc), "caller is not the SFC contract"); _; } modifier onlyDriver() { require(msg.sender == address(driver), "caller is not the NodeDriver contract"); _; } function migrateTo(address newDriverAuth) external onlyOwner { driver.setBackend(newDriverAuth); } function _execute(address executable, address newOwner, bytes32 selfCodeHash, bytes32 driverCodeHash) internal { _transferOwnership(executable); NodeDriverExecutable(executable).execute(); _transferOwnership(newOwner); //require(driver.backend() == address(this), "ownership of driver is lost"); require(_getCodeHash(address(this)) == selfCodeHash, "self code hash doesn't match"); require(_getCodeHash(address(driver)) == driverCodeHash, "driver code hash doesn't match"); } function execute(address executable) external onlyOwner { _execute(executable, owner(), _getCodeHash(address(this)), _getCodeHash(address(driver))); } function mutExecute(address executable, address newOwner, bytes32 selfCodeHash, bytes32 driverCodeHash) external onlyOwner { _execute(executable, newOwner, selfCodeHash, driverCodeHash); } function incBalance(address acc, uint256 diff) external onlySFC { require(acc == address(sfc), "recipient is not the SFC contract"); driver.setBalance(acc, address(acc).balance.add(diff)); } function upgradeCode(address acc, address from) external onlyOwner { require(isContract(acc) && isContract(from), "not a contract"); driver.copyCode(acc, from); } function copyCode(address acc, address from) external onlyOwner { driver.copyCode(acc, from); } function incNonce(address acc, uint256 diff) external onlyOwner { driver.incNonce(acc, diff); } function updateNetworkRules(bytes calldata diff) external onlyOwner { driver.updateNetworkRules(diff); } function updateMinGasPrice(uint256 minGasPrice) external onlySFC { driver.updateNetworkRules(bytes(strConcat("{\"Economy\":{\"MinGasPrice\":", uint256ToStr(minGasPrice), "}}"))); } function updateNetworkVersion(uint256 version) external onlyOwner { driver.updateNetworkVersion(version); } function advanceEpochs(uint256 num) external onlyOwner { driver.advanceEpochs(num); } function updateValidatorWeight(uint256 validatorID, uint256 value) external onlySFC { driver.updateValidatorWeight(validatorID, value); } function updateValidatorPubkey(uint256 validatorID, bytes calldata pubkey) external onlySFC { driver.updateValidatorPubkey(validatorID, pubkey); } function setGenesisValidator(address _auth, uint256 validatorID, bytes calldata pubkey, uint256 status, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedEpoch, uint256 deactivatedTime) external onlyDriver { sfc.setGenesisValidator(_auth, validatorID, pubkey, status, createdEpoch, createdTime, deactivatedEpoch, deactivatedTime); } function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake, uint256 lockedStake, uint256 lockupFromEpoch, uint256 lockupEndTime, uint256 lockupDuration, uint256 earlyUnlockPenalty, uint256 rewards) external onlyDriver { sfc.setGenesisDelegation(delegator, toValidatorID, stake, lockedStake, lockupFromEpoch, lockupEndTime, lockupDuration, earlyUnlockPenalty, rewards); } function deactivateValidator(uint256 validatorID, uint256 status) external onlyDriver { sfc.deactivateValidator(validatorID, status); } function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyDriver { sfc.sealEpochValidators(nextValidatorIDs); } function sealEpoch(uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee, uint256 usedGas) external onlyDriver { sfc.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee, usedGas); } function isContract(address account) internal view returns (bool) { uint256 size; // solhint-disable-next-line no-inline-assembly assembly {size := extcodesize(account)} return size > 0; } function decimalsNum(uint256 num) internal pure returns (uint256) { uint decimals; while (num != 0) { decimals++; num /= 10; } return decimals; } function uint256ToStr(uint256 num) internal pure returns (string memory) { if (num == 0) { return "0"; } uint decimals = decimalsNum(num); bytes memory bstr = new bytes(decimals); uint strIdx = decimals - 1; while (num != 0) { bstr[strIdx] = byte(uint8(48 + num % 10)); num /= 10; strIdx--; } return string(bstr); } function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory) { bytes memory _ba = bytes(_a); bytes memory _bb = bytes(_b); bytes memory _bc = bytes(_c); string memory abc = new string(_ba.length + _bb.length + _bc.length); bytes memory babc = bytes(abc); uint k = 0; uint i = 0; for (i = 0; i < _ba.length; i++) { babc[k++] = _ba[i]; } for (i = 0; i < _bb.length; i++) { babc[k++] = _bb[i]; } for (i = 0; i < _bc.length; i++) { babc[k++] = _bc[i]; } return string(babc); } function _getCodeHash(address addr) internal view returns (bytes32) { bytes32 codeHash; assembly {codeHash := extcodehash(addr)} return codeHash; } } contract NodeDriver is Initializable { uint256 private erased0; NodeDriverAuth internal backend; EVMWriter internal evmWriter; event UpdatedBackend(address indexed backend); function setBackend(address _backend) external onlyBackend { emit UpdatedBackend(_backend); backend = NodeDriverAuth(_backend); } modifier onlyBackend() { require(msg.sender == address(backend), "caller is not the backend"); _; } event UpdateValidatorWeight(uint256 indexed validatorID, uint256 weight); event UpdateValidatorPubkey(uint256 indexed validatorID, bytes pubkey); event UpdateNetworkRules(bytes diff); event UpdateNetworkVersion(uint256 version); event AdvanceEpochs(uint256 num); function initialize(address _backend, address _evmWriterAddress) external initializer { backend = NodeDriverAuth(_backend); emit UpdatedBackend(_backend); evmWriter = EVMWriter(_evmWriterAddress); } function setBalance(address acc, uint256 value) external onlyBackend { evmWriter.setBalance(acc, value); } function copyCode(address acc, address from) external onlyBackend { evmWriter.copyCode(acc, from); } function swapCode(address acc, address with) external onlyBackend { evmWriter.swapCode(acc, with); } function setStorage(address acc, bytes32 key, bytes32 value) external onlyBackend { evmWriter.setStorage(acc, key, value); } function incNonce(address acc, uint256 diff) external onlyBackend { evmWriter.incNonce(acc, diff); } function updateNetworkRules(bytes calldata diff) external onlyBackend { emit UpdateNetworkRules(diff); } function updateNetworkVersion(uint256 version) external onlyBackend { emit UpdateNetworkVersion(version); } function advanceEpochs(uint256 num) external onlyBackend { emit AdvanceEpochs(num); } function updateValidatorWeight(uint256 validatorID, uint256 value) external onlyBackend { emit UpdateValidatorWeight(validatorID, value); } function updateValidatorPubkey(uint256 validatorID, bytes calldata pubkey) external onlyBackend { emit UpdateValidatorPubkey(validatorID, pubkey); } modifier onlyNode() { require(msg.sender == address(0), "not callable"); _; } // Methods which are called only by the node function setGenesisValidator(address _auth, uint256 validatorID, bytes calldata pubkey, uint256 status, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedEpoch, uint256 deactivatedTime) external onlyNode { backend.setGenesisValidator(_auth, validatorID, pubkey, status, createdEpoch, createdTime, deactivatedEpoch, deactivatedTime); } function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake, uint256 lockedStake, uint256 lockupFromEpoch, uint256 lockupEndTime, uint256 lockupDuration, uint256 earlyUnlockPenalty, uint256 rewards) external onlyNode { backend.setGenesisDelegation(delegator, toValidatorID, stake, lockedStake, lockupFromEpoch, lockupEndTime, lockupDuration, earlyUnlockPenalty, rewards); } function deactivateValidator(uint256 validatorID, uint256 status) external onlyNode { backend.deactivateValidator(validatorID, status); } function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyNode { backend.sealEpochValidators(nextValidatorIDs); } function sealEpoch(uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee) external onlyNode { backend.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee, 841669690); } function sealEpochV1(uint256[] calldata offlineTimes, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee, uint256 usedGas) external onlyNode { backend.sealEpoch(offlineTimes, offlineBlocks, uptimes, originatedTxsFee, usedGas); } } interface EVMWriter { function setBalance(address acc, uint256 value) external; function copyCode(address acc, address from) external; function swapCode(address acc, address with) external; function setStorage(address acc, bytes32 key, bytes32 value) external; function incNonce(address acc, uint256 diff) external; }
pragma solidity ^0.5.0; import "./NodeDriver.sol"; import "../ownership/Ownable.sol"; import "./ConstantsManager.sol"; contract SFCState is Initializable, Ownable { using SafeMath for uint256; /** * @dev The staking for validation */ struct Validator { uint256 status; uint256 deactivatedTime; uint256 deactivatedEpoch; uint256 receivedStake; uint256 createdEpoch; uint256 createdTime; address auth; } NodeDriverAuth internal node; struct Rewards { uint256 lockupExtraReward; uint256 lockupBaseReward; uint256 unlockedReward; } uint256 public currentSealedEpoch; mapping(uint256 => Validator) public getValidator; mapping(address => uint256) public getValidatorID; mapping(uint256 => bytes) public getValidatorPubkey; uint256 public lastValidatorID; uint256 public totalStake; uint256 public totalActiveStake; uint256 public totalSlashedStake; mapping(address => mapping(uint256 => Rewards)) internal _rewardsStash; // addr, validatorID -> Rewards mapping(address => mapping(uint256 => uint256)) public stashedRewardsUntilEpoch; struct WithdrawalRequest { uint256 epoch; uint256 time; uint256 amount; } mapping(address => mapping(uint256 => mapping(uint256 => WithdrawalRequest))) public getWithdrawalRequest; struct LockedDelegation { uint256 lockedStake; uint256 fromEpoch; uint256 endTime; uint256 duration; } mapping(address => mapping(uint256 => uint256)) public getStake; mapping(address => mapping(uint256 => LockedDelegation)) public getLockupInfo; mapping(address => mapping(uint256 => Rewards)) public getStashedLockupRewards; struct EpochSnapshot { mapping(uint256 => uint256) receivedStake; mapping(uint256 => uint256) accumulatedRewardPerToken; mapping(uint256 => uint256) accumulatedUptime; mapping(uint256 => uint256) accumulatedOriginatedTxsFee; mapping(uint256 => uint256) offlineTime; mapping(uint256 => uint256) offlineBlocks; uint256[] validatorIDs; uint256 endTime; uint256 epochFee; uint256 totalBaseRewardWeight; uint256 totalTxRewardWeight; uint256 baseRewardPerSecond; uint256 totalStake; uint256 totalSupply; } uint256 private erased0; uint256 public totalSupply; mapping(uint256 => EpochSnapshot) public getEpochSnapshot; uint256 private erased1; uint256 private erased2; mapping(uint256 => uint256) public slashingRefundRatio; // validator ID -> (slashing refund ratio) address public stakeTokenizerAddress; uint256 private erased3; uint256 private erased4; uint256 public minGasPrice; address public treasuryAddress; address internal libAddress; ConstantsManager internal c; address public voteBookAddress; address internal sftmFinalizer; struct Penalty { uint256 amount; uint256 end; } // delegator => validatorID => penalties info mapping(address => mapping(uint256 => Penalty[])) public getStashedPenalties; mapping(uint256 => uint256) internal validatorPubkeyChanges; mapping(bytes32 => uint256) internal pubkeyHashToValidatorID; address public redirectionAuthorizer; mapping(address => address) public getRedirectionRequest; mapping(address => address) public getRedirection; }
pragma solidity ^0.5.0; import "./GasPriceConstants.sol"; import "../version/Version.sol"; import "./SFCBase.sol"; /** * @dev Stakers contract defines data structure and methods for validators / validators. */ contract SFC is SFCBase, Version { function _delegate(address implementation) internal { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize) switch result // delegatecall returns 0 on error. case 0 {revert(0, returndatasize)} default {return (0, returndatasize)} } } function() payable external { require(msg.data.length != 0, "transfers not allowed"); _delegate(libAddress); } /* Getters */ function getEpochValidatorIDs(uint256 epoch) public view returns (uint256[] memory) { return getEpochSnapshot[epoch].validatorIDs; } function getEpochReceivedStake(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].receivedStake[validatorID]; } function getEpochAccumulatedRewardPerToken(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].accumulatedRewardPerToken[validatorID]; } function getEpochAccumulatedUptime(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].accumulatedUptime[validatorID]; } function getEpochAccumulatedOriginatedTxsFee(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].accumulatedOriginatedTxsFee[validatorID]; } function getEpochOfflineTime(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].offlineTime[validatorID]; } function getEpochOfflineBlocks(uint256 epoch, uint256 validatorID) public view returns (uint256) { return getEpochSnapshot[epoch].offlineBlocks[validatorID]; } function rewardsStash(address delegator, uint256 validatorID) public view returns (uint256) { Rewards memory stash = _rewardsStash[delegator][validatorID]; return stash.lockupBaseReward.add(stash.lockupExtraReward).add(stash.unlockedReward); } /* Constructor */ function initialize(uint256 sealedEpoch, uint256 _totalSupply, address nodeDriver, address lib, address _c, address owner) external initializer { Ownable.initialize(owner); currentSealedEpoch = sealedEpoch; node = NodeDriverAuth(nodeDriver); libAddress = lib; c = ConstantsManager(_c); totalSupply = _totalSupply; minGasPrice = GP.initialMinGasPrice(); getEpochSnapshot[sealedEpoch].endTime = _now(); } function updateStakeTokenizerAddress(address addr) onlyOwner external { stakeTokenizerAddress = addr; } function updateLibAddress(address v) onlyOwner external { libAddress = v; } function updateTreasuryAddress(address v) onlyOwner external { treasuryAddress = v; } function updateConstsAddress(address v) onlyOwner external { c = ConstantsManager(v); } function constsAddress() external view returns (address) { return address(c); } function updateVoteBookAddress(address v) onlyOwner external { voteBookAddress = v; } function updateSFTMFinalizer(address v) external onlyOwner { sftmFinalizer = v; } function migrateValidatorPubkeyUniquenessFlag(uint256 start, uint256 end) external { for (uint256 vid = start; vid < end; vid++) { bytes memory pubkey = getValidatorPubkey[vid]; if (pubkey.length > 0 && pubkeyHashToValidatorID[keccak256(pubkey)] != vid) { require(pubkeyHashToValidatorID[keccak256(pubkey)] == 0, "already exists"); pubkeyHashToValidatorID[keccak256(pubkey)] = vid; } } } function updateValidatorPubkey(bytes calldata pubkey) external { require(getValidator[1].auth == 0x541E408443A592C38e01Bed0cB31f9De8c1322d0, "not mainnet"); require(pubkey.length == 66 && pubkey[0] == 0xc0, "malformed pubkey"); uint256 validatorID = getValidatorID[msg.sender]; require(validatorID <= 59, "not legacy validator"); require(_validatorExists(validatorID), "validator doesn't exist"); require(keccak256(pubkey) != keccak256(getValidatorPubkey[validatorID]), "same pubkey"); require(pubkeyHashToValidatorID[keccak256(pubkey)] == 0, "already used"); require(validatorPubkeyChanges[validatorID] == 0, "allowed only once"); validatorPubkeyChanges[validatorID]++; pubkeyHashToValidatorID[keccak256(pubkey)] = validatorID; getValidatorPubkey[validatorID] = pubkey; _syncValidator(validatorID, true); } function setRedirectionAuthorizer(address v) onlyOwner external { require(redirectionAuthorizer != v, "same"); redirectionAuthorizer = v; } event AnnouncedRedirection(address indexed from, address indexed to); function announceRedirection(address to) external { emit AnnouncedRedirection(msg.sender, to); } function initiateRedirection(address from, address to) external { require(msg.sender == redirectionAuthorizer, "not authorized"); require(getRedirection[from] != to, "already complete"); require(from != to, "same address"); getRedirectionRequest[from] = to; } function redirect(address to) external { address from = msg.sender; require(to != address(0), "zero address"); require(getRedirectionRequest[from] == to, "no request"); getRedirection[from] = to; getRedirectionRequest[from] = address(0); } /* Epoch callbacks */ function _sealEpoch_offline(EpochSnapshot storage snapshot, uint256[] memory validatorIDs, uint256[] memory offlineTime, uint256[] memory offlineBlocks) internal { // mark offline nodes for (uint256 i = 0; i < validatorIDs.length; i++) { if (offlineBlocks[i] > c.offlinePenaltyThresholdBlocksNum() && offlineTime[i] >= c.offlinePenaltyThresholdTime()) { _setValidatorDeactivated(validatorIDs[i], OFFLINE_BIT); _syncValidator(validatorIDs[i], false); } // log data snapshot.offlineTime[validatorIDs[i]] = offlineTime[i]; snapshot.offlineBlocks[validatorIDs[i]] = offlineBlocks[i]; } } struct _SealEpochRewardsCtx { uint256[] baseRewardWeights; uint256 totalBaseRewardWeight; uint256[] txRewardWeights; uint256 totalTxRewardWeight; uint256 epochFee; } function _sealEpoch_rewards(uint256 epochDuration, EpochSnapshot storage snapshot, EpochSnapshot storage prevSnapshot, uint256[] memory validatorIDs, uint256[] memory uptimes, uint256[] memory accumulatedOriginatedTxsFee) internal { _SealEpochRewardsCtx memory ctx = _SealEpochRewardsCtx(new uint[](validatorIDs.length), 0, new uint[](validatorIDs.length), 0, 0); for (uint256 i = 0; i < validatorIDs.length; i++) { uint256 prevAccumulatedTxsFee = prevSnapshot.accumulatedOriginatedTxsFee[validatorIDs[i]]; uint256 originatedTxsFee = 0; if (accumulatedOriginatedTxsFee[i] > prevAccumulatedTxsFee) { originatedTxsFee = accumulatedOriginatedTxsFee[i] - prevAccumulatedTxsFee; } // txRewardWeight = {originatedTxsFee} * {uptime} // originatedTxsFee is roughly proportional to {uptime} * {stake}, so the whole formula is roughly // {stake} * {uptime} ^ 2 ctx.txRewardWeights[i] = originatedTxsFee * uptimes[i] / epochDuration; ctx.totalTxRewardWeight = ctx.totalTxRewardWeight.add(ctx.txRewardWeights[i]); ctx.epochFee = ctx.epochFee.add(originatedTxsFee); } for (uint256 i = 0; i < validatorIDs.length; i++) { // baseRewardWeight = {stake} * {uptime ^ 2} ctx.baseRewardWeights[i] = (((snapshot.receivedStake[validatorIDs[i]] * uptimes[i]) / epochDuration) * uptimes[i]) / epochDuration; ctx.totalBaseRewardWeight = ctx.totalBaseRewardWeight.add(ctx.baseRewardWeights[i]); } for (uint256 i = 0; i < validatorIDs.length; i++) { uint256 rawReward = _calcRawValidatorEpochBaseReward(epochDuration, c.baseRewardPerSecond(), ctx.baseRewardWeights[i], ctx.totalBaseRewardWeight); rawReward = rawReward.add(_calcRawValidatorEpochTxReward(ctx.epochFee, ctx.txRewardWeights[i], ctx.totalTxRewardWeight)); uint256 validatorID = validatorIDs[i]; address validatorAddr = getValidator[validatorID].auth; // accounting validator's commission uint256 commissionRewardFull = _calcValidatorCommission(rawReward, c.validatorCommission()); uint256 selfStake = getStake[validatorAddr][validatorID]; if (selfStake != 0) { uint256 lCommissionRewardFull = (commissionRewardFull * getLockedStake(validatorAddr, validatorID)) / selfStake; uint256 uCommissionRewardFull = commissionRewardFull - lCommissionRewardFull; Rewards memory lCommissionReward = _scaleLockupReward(lCommissionRewardFull, getLockupInfo[validatorAddr][validatorID].duration); Rewards memory uCommissionReward = _scaleLockupReward(uCommissionRewardFull, 0); _rewardsStash[validatorAddr][validatorID] = sumRewards(_rewardsStash[validatorAddr][validatorID], lCommissionReward, uCommissionReward); getStashedLockupRewards[validatorAddr][validatorID] = sumRewards(getStashedLockupRewards[validatorAddr][validatorID], lCommissionReward, uCommissionReward); } // accounting reward per token for delegators uint256 delegatorsReward = rawReward - commissionRewardFull; // note: use latest stake for the sake of rewards distribution accuracy, not snapshot.receivedStake uint256 receivedStake = getValidator[validatorID].receivedStake; uint256 rewardPerToken = 0; if (receivedStake != 0) { rewardPerToken = (delegatorsReward * Decimal.unit()) / receivedStake; } snapshot.accumulatedRewardPerToken[validatorID] = prevSnapshot.accumulatedRewardPerToken[validatorID] + rewardPerToken; snapshot.accumulatedOriginatedTxsFee[validatorID] = accumulatedOriginatedTxsFee[i]; snapshot.accumulatedUptime[validatorID] = prevSnapshot.accumulatedUptime[validatorID] + uptimes[i]; } snapshot.epochFee = ctx.epochFee; snapshot.totalBaseRewardWeight = ctx.totalBaseRewardWeight; snapshot.totalTxRewardWeight = ctx.totalTxRewardWeight; if (totalSupply > snapshot.epochFee) { totalSupply -= snapshot.epochFee; } else { totalSupply = 0; } // transfer 10% of fees to treasury if (treasuryAddress != address(0)) { uint256 feeShare = ctx.epochFee * c.treasuryFeeShare() / Decimal.unit(); _mintNativeToken(feeShare); treasuryAddress.call.value(feeShare).gas(1000000)(""); } } function _sealEpoch_minGasPrice(uint256 epochDuration, uint256 epochGas) internal { // change minGasPrice proportionally to the difference between target and received epochGas uint256 targetEpochGas = epochDuration * c.targetGasPowerPerSecond() + 1; uint256 gasPriceDeltaRatio = epochGas * Decimal.unit() / targetEpochGas; uint256 counterweight = c.gasPriceBalancingCounterweight(); // scale down the change speed (estimate gasPriceDeltaRatio ^ (epochDuration / counterweight)) gasPriceDeltaRatio = (epochDuration * gasPriceDeltaRatio + counterweight * Decimal.unit()) / (epochDuration + counterweight); // limit the max/min possible delta in one epoch gasPriceDeltaRatio = GP.trimGasPriceChangeRatio(gasPriceDeltaRatio); // apply the ratio uint256 newMinGasPrice = minGasPrice * gasPriceDeltaRatio / Decimal.unit(); // limit the max/min possible minGasPrice newMinGasPrice = GP.trimMinGasPrice(newMinGasPrice); // apply new minGasPrice minGasPrice = newMinGasPrice; } function sealEpoch(uint256[] calldata offlineTime, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee, uint256 epochGas) external onlyDriver { EpochSnapshot storage snapshot = getEpochSnapshot[currentEpoch()]; uint256[] memory validatorIDs = snapshot.validatorIDs; _sealEpoch_offline(snapshot, validatorIDs, offlineTime, offlineBlocks); { EpochSnapshot storage prevSnapshot = getEpochSnapshot[currentSealedEpoch]; uint256 epochDuration = 1; if (_now() > prevSnapshot.endTime) { epochDuration = _now() - prevSnapshot.endTime; } _sealEpoch_rewards(epochDuration, snapshot, prevSnapshot, validatorIDs, uptimes, originatedTxsFee); _sealEpoch_minGasPrice(epochDuration, epochGas); } currentSealedEpoch = currentEpoch(); snapshot.endTime = _now(); snapshot.baseRewardPerSecond = c.baseRewardPerSecond(); snapshot.totalSupply = totalSupply; } function sealEpochValidators(uint256[] calldata nextValidatorIDs) external onlyDriver { EpochSnapshot storage snapshot = getEpochSnapshot[currentEpoch()]; // fill data for the next snapshot for (uint256 i = 0; i < nextValidatorIDs.length; i++) { uint256 validatorID = nextValidatorIDs[i]; uint256 receivedStake = getValidator[validatorID].receivedStake; snapshot.receivedStake[validatorID] = receivedStake; snapshot.totalStake = snapshot.totalStake.add(receivedStake); } snapshot.validatorIDs = nextValidatorIDs; node.updateMinGasPrice(minGasPrice); } }
pragma solidity ^0.5.0; import "./ERC20.sol"; /** * @title Burnable Token * @dev Token that can be irreversibly burned (destroyed). */ contract ERC20Burnable is ERC20 { /** * @dev Burns a specific amount of tokens. * @param value The amount of token to be burned. */ function burn(uint256 value) public { _burn(msg.sender, value); } /** * @dev Burns a specific amount of tokens from the target address and decrements allowance * @param from address The address which you want to send tokens from * @param value uint256 The amount of token to be burned */ function burnFrom(address from, uint256 value) public { _burnFrom(from, value); } /** * @dev Overrides ERC20._burn in order for burn and burnFrom to emit * an additional Burn event. */ function _burn(address who, uint256 value) internal { super._burn(who, value); } }
pragma solidity ^0.5.0; import "./ERC20.sol"; import "./MinterRole.sol"; /** * @title ERC20Mintable * @dev ERC20 minting logic */ contract ERC20Mintable is ERC20, MinterRole { event MintingFinished(); bool private _mintingFinished = false; modifier onlyBeforeMintingFinished() { require(!_mintingFinished); _; } /** * @return true if the minting is finished. */ function mintingFinished() public view returns (bool) { return _mintingFinished; } /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. * @param amount The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint( address to, uint256 amount ) public onlyMinter onlyBeforeMintingFinished returns (bool) { _mint(to, amount); return true; } /** * @dev Function to stop minting new tokens. * @return True if the operation was successful. */ function finishMinting() public onlyMinter onlyBeforeMintingFinished returns (bool) { _mintingFinished = true; emit MintingFinished(); return true; } }
pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
pragma solidity ^0.5.0; import "../common/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be aplied to your functions to restrict their use to * the owner. */ contract Ownable is Initializable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function initialize(address sender) internal initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * > Note: 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 Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; }
pragma solidity ^0.5.0; interface SFCI { event CreatedValidator(uint256 indexed validatorID, address indexed auth, uint256 createdEpoch, uint256 createdTime); event Delegated(address indexed delegator, uint256 indexed toValidatorID, uint256 amount); event Undelegated(address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount); event Withdrawn(address indexed delegator, uint256 indexed toValidatorID, uint256 indexed wrID, uint256 amount); event ClaimedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward); event RestakedRewards(address indexed delegator, uint256 indexed toValidatorID, uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward); event BurntFTM(uint256 amount); event LockedUpStake(address indexed delegator, uint256 indexed validatorID, uint256 duration, uint256 amount); event UnlockedStake(address indexed delegator, uint256 indexed validatorID, uint256 amount, uint256 penalty); event UpdatedSlashingRefundRatio(uint256 indexed validatorID, uint256 refundRatio); event RefundedSlashedLegacyDelegation(address indexed delegator, uint256 indexed validatorID, uint256 amount); event DeactivatedValidator(uint256 indexed validatorID, uint256 deactivatedEpoch, uint256 deactivatedTime); event ChangedValidatorStatus(uint256 indexed validatorID, uint256 status); event AnnouncedRedirection(address indexed from, address indexed to); function currentSealedEpoch() external view returns (uint256); function getEpochSnapshot(uint256) external view returns (uint256 endTime, uint256 epochFee, uint256 totalBaseRewardWeight, uint256 totalTxRewardWeight, uint256 _baseRewardPerSecond, uint256 totalStake, uint256 totalSupply); function getLockupInfo(address, uint256) external view returns (uint256 lockedStake, uint256 fromEpoch, uint256 endTime, uint256 duration); function getStake(address, uint256) external view returns (uint256); function getStashedLockupRewards(address, uint256) external view returns (uint256 lockupExtraReward, uint256 lockupBaseReward, uint256 unlockedReward); function getValidator(uint256) external view returns (uint256 status, uint256 deactivatedTime, uint256 deactivatedEpoch, uint256 receivedStake, uint256 createdEpoch, uint256 createdTime, address auth); function getValidatorID(address) external view returns (uint256); function getValidatorPubkey(uint256) external view returns (bytes memory); function getWithdrawalRequest(address, uint256, uint256) external view returns (uint256 epoch, uint256 time, uint256 amount); function isOwner() external view returns (bool); function lastValidatorID() external view returns (uint256); function minGasPrice() external view returns (uint256); function owner() external view returns (address); function renounceOwnership() external; function slashingRefundRatio(uint256) external view returns (uint256); function stakeTokenizerAddress() external view returns (address); function stashedRewardsUntilEpoch(address, uint256) external view returns (uint256); function totalActiveStake() external view returns (uint256); function totalSlashedStake() external view returns (uint256); function totalStake() external view returns (uint256); function totalSupply() external view returns (uint256); function transferOwnership(address newOwner) external; function treasuryAddress() external view returns (address); function version() external pure returns (bytes3); function currentEpoch() external view returns (uint256); function updateConstsAddress(address v) external; function constsAddress() external view returns (address); function getEpochValidatorIDs(uint256 epoch) external view returns (uint256[] memory); function getEpochReceivedStake(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochAccumulatedRewardPerToken(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochAccumulatedUptime(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochAccumulatedOriginatedTxsFee(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochOfflineTime(uint256 epoch, uint256 validatorID) external view returns (uint256); function getEpochOfflineBlocks(uint256 epoch, uint256 validatorID) external view returns (uint256); function rewardsStash(address delegator, uint256 validatorID) external view returns (uint256); function getLockedStake(address delegator, uint256 toValidatorID) external view returns (uint256); function createValidator(bytes calldata pubkey) external payable; function getSelfStake(uint256 validatorID) external view returns (uint256); function delegate(uint256 toValidatorID) external payable; function undelegate(uint256 toValidatorID, uint256 wrID, uint256 amount) external; function isSlashed(uint256 validatorID) external view returns (bool); function withdraw(uint256 toValidatorID, uint256 wrID) external; function deactivateValidator(uint256 validatorID, uint256 status) external; function pendingRewards(address delegator, uint256 toValidatorID) external view returns (uint256); function stashRewards(address delegator, uint256 toValidatorID) external; function claimRewards(uint256 toValidatorID) external; function restakeRewards(uint256 toValidatorID) external; function updateBaseRewardPerSecond(uint256 value) external; function updateOfflinePenaltyThreshold(uint256 blocksNum, uint256 time) external; function updateSlashingRefundRatio(uint256 validatorID, uint256 refundRatio) external; function updateStakeTokenizerAddress(address addr) external; function updateTreasuryAddress(address v) external; function burnFTM(uint256 amount) external; function sealEpoch(uint256[] calldata offlineTime, uint256[] calldata offlineBlocks, uint256[] calldata uptimes, uint256[] calldata originatedTxsFee, uint256 epochGas) external; function sealEpochValidators(uint256[] calldata nextValidatorIDs) external; function isLockedUp(address delegator, uint256 toValidatorID) external view returns (bool); function getUnlockedStake(address delegator, uint256 toValidatorID) external view returns (uint256); function lockStake(uint256 toValidatorID, uint256 lockupDuration, uint256 amount) external; function relockStake(uint256 toValidatorID, uint256 lockupDuration, uint256 amount) external; function unlockStake(uint256 toValidatorID, uint256 amount) external returns (uint256); function initialize(uint256 sealedEpoch, uint256 _totalSupply, address nodeDriver, address lib, address consts, address _owner) external; function setGenesisValidator(address auth, uint256 validatorID, bytes calldata pubkey, uint256 status, uint256 createdEpoch, uint256 createdTime, uint256 deactivatedEpoch, uint256 deactivatedTime) external; function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake, uint256 lockedStake, uint256 lockupFromEpoch, uint256 lockupEndTime, uint256 lockupDuration, uint256 earlyUnlockPenalty, uint256 rewards) external; function updateVoteBookAddress(address v) external; function voteBookAddress() external view returns (address); function liquidateSFTM(address delegator, uint256 toValidatorID, uint256 amount) external; function updateSFTMFinalizer(address v) external; function updateValidatorPubkey(bytes calldata pubkey) external; function migrateValidatorPubkeyUniquenessFlag(uint256 start, uint256 end) external; function setRedirectionAuthorizer(address v) external; function announceRedirection(address to) external; function initiateRedirection(address from, address to) external; function redirect(address to) external; }
pragma solidity ^0.5.0; import "../common/SafeMath.sol"; import "../ownership/Ownable.sol"; import "../common/Decimal.sol"; contract ConstantsManager is Ownable { using SafeMath for uint256; // Minimum amount of stake for a validator, i.e., 500000 FTM uint256 public minSelfStake; // Maximum ratio of delegations a validator can have, say, 15 times of self-stake uint256 public maxDelegatedRatio; // The commission fee in percentage a validator will get from a delegation, e.g., 15% uint256 public validatorCommission; // The percentage of fees to burn, e.g., 20% uint256 public burntFeeShare; // The percentage of fees to transfer to treasury address, e.g., 10% uint256 public treasuryFeeShare; // The ratio of the reward rate at base rate (no lock), e.g., 30% uint256 public unlockedRewardRatio; // The minimum duration of a stake/delegation lockup, e.g. 2 weeks uint256 public minLockupDuration; // The maximum duration of a stake/delegation lockup, e.g. 1 year uint256 public maxLockupDuration; // the number of epochs that undelegated stake is locked for uint256 public withdrawalPeriodEpochs; // the number of seconds that undelegated stake is locked for uint256 public withdrawalPeriodTime; uint256 public baseRewardPerSecond; uint256 public offlinePenaltyThresholdBlocksNum; uint256 public offlinePenaltyThresholdTime; uint256 public targetGasPowerPerSecond; uint256 public gasPriceBalancingCounterweight; address private secondaryOwner_erased; // event SecondaryOwnershipTransferred(address indexed previousOwner, address indexed newOwner); function initialize() external initializer { Ownable.initialize(msg.sender); } // function setSecondaryOwner(address v) onlyOwner external { // emit SecondaryOwnershipTransferred(secondaryOwner, v); // secondaryOwner = v; // } function updateMinSelfStake(uint256 v) onlyOwner external { require(v >= 100000 * 1e18, "too small value"); require(v <= 10000000 * 1e18, "too large value"); minSelfStake = v; } function updateMaxDelegatedRatio(uint256 v) onlyOwner external { require(v >= Decimal.unit(), "too small value"); require(v <= 31 * Decimal.unit(), "too large value"); maxDelegatedRatio = v; } function updateValidatorCommission(uint256 v) onlyOwner external { require(v <= Decimal.unit() / 2, "too large value"); validatorCommission = v; } function updateBurntFeeShare(uint256 v) onlyOwner external { require(v <= Decimal.unit() / 2, "too large value"); burntFeeShare = v; } function updateTreasuryFeeShare(uint256 v) onlyOwner external { require(v <= Decimal.unit() / 2, "too large value"); treasuryFeeShare = v; } function updateUnlockedRewardRatio(uint256 v) onlyOwner external { require(v >= (5 * Decimal.unit()) / 100, "too small value"); require(v <= Decimal.unit() / 2, "too large value"); unlockedRewardRatio = v; } function updateMinLockupDuration(uint256 v) onlyOwner external { require(v >= 86400, "too small value"); require(v <= 86400 * 30, "too large value"); minLockupDuration = v; } function updateMaxLockupDuration(uint256 v) onlyOwner external { require(v >= 86400 * 30, "too small value"); require(v <= 86400 * 1460, "too large value"); maxLockupDuration = v; } function updateWithdrawalPeriodEpochs(uint256 v) onlyOwner external { require(v >= 2, "too small value"); require(v <= 100, "too large value"); withdrawalPeriodEpochs = v; } function updateWithdrawalPeriodTime(uint256 v) onlyOwner external { require(v >= 86400, "too small value"); require(v <= 30 * 86400, "too large value"); withdrawalPeriodTime = v; } function updateBaseRewardPerSecond(uint256 v) onlyOwner external { require(v >= 0.5 * 1e18, "too small value"); require(v <= 32 * 1e18, "too large value"); baseRewardPerSecond = v; } function updateOfflinePenaltyThresholdTime(uint256 v) onlyOwner external { require(v >= 86400, "too small value"); require(v <= 10 * 86400, "too large value"); offlinePenaltyThresholdTime = v; } function updateOfflinePenaltyThresholdBlocksNum(uint256 v) onlyOwner external { require(v >= 100, "too small value"); require(v <= 1000000, "too large value"); offlinePenaltyThresholdBlocksNum = v; } function updateTargetGasPowerPerSecond(uint256 v) onlyOwner external { require(v >= 1000000, "too small value"); require(v <= 500000000, "too large value"); targetGasPowerPerSecond = v; } function updateGasPriceBalancingCounterweight(uint256 v) onlyOwner external { require(v >= 100, "too small value"); require(v <= 10 * 86400, "too large value"); gasPriceBalancingCounterweight = v; } }
pragma solidity ^0.5.0; /** * @dev Version contract gives the versioning information of the implementation contract */ contract Version { /** * @dev Returns the address of the current owner. */ function version() public pure returns (bytes3) { // version 3.0.5 return "305"; } }
pragma solidity ^0.5.0; import "../../common/SafeMath.sol"; import "./IERC20.sol"; import "../../common/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Initializable, IERC20 { using SafeMath for uint256; mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(msg.sender, recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(msg.sender, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _transfer(sender, recipient, amount); _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: burn amount exceeds allowance")); } uint256[50] private ______gap; }
pragma solidity ^0.5.0; import "./Roles.sol"; contract MinterRole { using Roles for Roles.Role; event MinterAdded(address indexed account); event MinterRemoved(address indexed account); Roles.Role private minters; modifier onlyMinter() { require(isMinter(msg.sender)); _; } function isMinter(address account) public view returns (bool) { return minters.has(account); } function renounceMinter() public { minters.remove(msg.sender); } function _removeMinter(address account) internal { minters.remove(account); emit MinterRemoved(account); } function _addMinter(address account) internal { minters.add(account); emit MinterAdded(account); } uint256[50] private ______gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
pragma solidity ^0.5.0; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping(address => bool) bearer; } /** * @dev give an account access to this role */ function add(Role storage role, address account) internal { require(account != address(0)); role.bearer[account] = true; } /** * @dev remove an account's access to this role */ function remove(Role storage role, address account) internal { require(account != address(0)); role.bearer[account] = false; } /** * @dev check if an account has this role * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0)); return role.bearer[account]; } }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "abi", "evm.bytecode", "evm.deployedBytecode", "evm.methodIdentifiers", "metadata" ], "": [ "ast" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BurntFTM","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"status","type":"uint256"}],"name":"ChangedValidatorStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockupExtraReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockupBaseReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockedReward","type":"uint256"}],"name":"ClaimedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":true,"internalType":"address","name":"auth","type":"address"},{"indexed":false,"internalType":"uint256","name":"createdEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"createdTime","type":"uint256"}],"name":"CreatedValidator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deactivatedEpoch","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deactivatedTime","type":"uint256"}],"name":"DeactivatedValidator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Delegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockedUpStake","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":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RefundedSlashedLegacyDelegation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockupExtraReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockupBaseReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockedReward","type":"uint256"}],"name":"RestakedRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"wrID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Undelegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"penalty","type":"uint256"}],"name":"UnlockedStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"validatorID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refundRatio","type":"uint256"}],"name":"UpdatedSlashingRefundRatio","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"wrID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"constant":false,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"_delStalePenalties","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"bool","name":"syncPubkey","type":"bool"}],"name":"_syncValidator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFTM","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"claimRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"createValidator","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSealedEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"uint256","name":"status","type":"uint256"}],"name":"deactivateValidator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"delegate","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getEpochSnapshot","outputs":[{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"epochFee","type":"uint256"},{"internalType":"uint256","name":"totalBaseRewardWeight","type":"uint256"},{"internalType":"uint256","name":"totalTxRewardWeight","type":"uint256"},{"internalType":"uint256","name":"baseRewardPerSecond","type":"uint256"},{"internalType":"uint256","name":"totalStake","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"getLockedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getLockupInfo","outputs":[{"internalType":"uint256","name":"lockedStake","type":"uint256"},{"internalType":"uint256","name":"fromEpoch","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getRedirection","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getRedirectionRequest","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"getSelfStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getStashedLockupRewards","outputs":[{"internalType":"uint256","name":"lockupExtraReward","type":"uint256"},{"internalType":"uint256","name":"lockupBaseReward","type":"uint256"},{"internalType":"uint256","name":"unlockedReward","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getStashedPenalties","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"getUnlockedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getValidator","outputs":[{"internalType":"uint256","name":"status","type":"uint256"},{"internalType":"uint256","name":"deactivatedTime","type":"uint256"},{"internalType":"uint256","name":"deactivatedEpoch","type":"uint256"},{"internalType":"uint256","name":"receivedStake","type":"uint256"},{"internalType":"uint256","name":"createdEpoch","type":"uint256"},{"internalType":"uint256","name":"createdTime","type":"uint256"},{"internalType":"address","name":"auth","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getValidatorID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getValidatorPubkey","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getWithdrawalRequest","outputs":[{"internalType":"uint256","name":"epoch","type":"uint256"},{"internalType":"uint256","name":"time","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"isLockedUp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"}],"name":"isSlashed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastValidatorID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"liquidateSFTM","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"lockupDuration","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"lockStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minGasPrice","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":true,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"address","name":"validatorAuth","type":"address"},{"internalType":"bool","name":"strict","type":"bool"},{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"recountVotes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"redirectionAuthorizer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"lockupDuration","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"relockStake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"restakeRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"lockedStake","type":"uint256"},{"internalType":"uint256","name":"lockupFromEpoch","type":"uint256"},{"internalType":"uint256","name":"lockupEndTime","type":"uint256"},{"internalType":"uint256","name":"lockupDuration","type":"uint256"},{"internalType":"uint256","name":"earlyUnlockPenalty","type":"uint256"},{"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"setGenesisDelegation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"auth","type":"address"},{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"bytes","name":"pubkey","type":"bytes"},{"internalType":"uint256","name":"status","type":"uint256"},{"internalType":"uint256","name":"createdEpoch","type":"uint256"},{"internalType":"uint256","name":"createdTime","type":"uint256"},{"internalType":"uint256","name":"deactivatedEpoch","type":"uint256"},{"internalType":"uint256","name":"deactivatedTime","type":"uint256"}],"name":"setGenesisValidator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slashingRefundRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stakeTokenizerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"delegator","type":"address"},{"internalType":"uint256","name":"toValidatorID","type":"uint256"}],"name":"stashRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stashedRewardsUntilEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalActiveStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSlashedStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"treasuryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"wrID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"undelegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unlockStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"validatorID","type":"uint256"},{"internalType":"uint256","name":"refundRatio","type":"uint256"}],"name":"updateSlashingRefundRatio","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"voteBookAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"toValidatorID","type":"uint256"},{"internalType":"uint256","name":"wrID","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600436106103555760003560e01c80637cacb1d6116101bb578063b5d89627116100f7578063cc8343aa11610095578063d96ed5051161006f578063d96ed50514610e4a578063de67f21514610e5f578063e9a505a714610e95578063f2fde38b14610eaa57610355565b8063cc8343aa14610da6578063cfd4766314610dd8578063cfdbb7cd14610e1157610355565b8063c3de580e116100d1578063c3de580e14610d28578063c5f956af14610d52578063c65ee0e114610d67578063c7be95de14610d9157610355565b8063b5d8962714610c4e578063b810e41114610cb9578063bd14d90714610cf257610355565b80638f32d59b116101645780639fa6dd351161013e5780639fa6dd3514610b30578063a45e115414610b4d578063a5a470ad14610ba5578063a86a056f14610c1557610355565b80638f32d59b14610a7e57806390a6c47514610aa757806396c7ee4614610ad157610355565b80638b0e9f3f116101955780638b0e9f3f14610a1b5780638cddb01514610a305780638da5cb5b14610a6957610355565b80637cacb1d614610952578063854873e114610967578063893675c614610a0657610355565b80633a488397116102955780635fab23a811610233578063715018a61161020d578063715018a6146108bc578063736de9ae146108d157806375dcf03014610904578063766718081461093d57610355565b80635fab23a8146108355780636099ecb21461084a578063670322f81461088357610355565b80634f7c4efb1161026f5780634f7c4efb146106fa5780634f864df41461072a5780634feb92f3146107605780635601fe011461080b57610355565b80633a48839714610658578063441a3e7014610697578063468f35ee146106c757610355565b806318f628d4116103025780631f270152116102dc5780631f2701521461053957806320c0849d1461059657806328f73148146105e157806339b80c00146105f657610355565b806318f628d4146104745780631d3ac42c146104d95780631e702f831461050957610355565b80630e559d82116103335780630e559d82146103f557806312622d0e1461042657806318160ddd1461045f57610355565b80630135b1db1461035a57806308c368741461039f5780630962ef79146103cb575b600080fd5b34801561036657600080fd5b5061038d6004803603602081101561037d57600080fd5b50356001600160a01b0316610edd565b60408051918252519081900360200190f35b3480156103ab57600080fd5b506103c9600480360360208110156103c257600080fd5b5035610eef565b005b3480156103d757600080fd5b506103c9600480360360208110156103ee57600080fd5b5035610fbb565b34801561040157600080fd5b5061040a61110e565b604080516001600160a01b039092168252519081900360200190f35b34801561043257600080fd5b5061038d6004803603604081101561044957600080fd5b506001600160a01b03813516906020013561111d565b34801561046b57600080fd5b5061038d6111a6565b34801561048057600080fd5b506103c9600480360361012081101561049857600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e08101359061010001356111ac565b3480156104e557600080fd5b5061038d600480360360408110156104fc57600080fd5b508035906020013561130e565b34801561051557600080fd5b506103c96004803603604081101561052c57600080fd5b50803590602001356115d4565b34801561054557600080fd5b506105786004803603606081101561055c57600080fd5b506001600160a01b0381351690602081013590604001356116ad565b60408051938452602084019290925282820152519081900360600190f35b3480156105a257600080fd5b506103c9600480360360808110156105b957600080fd5b506001600160a01b0381358116916020810135909116906040810135151590606001356116df565b3480156105ed57600080fd5b5061038d61187c565b34801561060257600080fd5b506106206004803603602081101561061957600080fd5b5035611882565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561066457600080fd5b506103c96004803603606081101561067b57600080fd5b506001600160a01b0381351690602081013590604001356118c4565b3480156106a357600080fd5b506103c9600480360360408110156106ba57600080fd5b5080359060200135611c79565b3480156106d357600080fd5b5061040a600480360360208110156106ea57600080fd5b50356001600160a01b0316611c91565b34801561070657600080fd5b506103c96004803603604081101561071d57600080fd5b5080359060200135611cac565b34801561073657600080fd5b506103c96004803603606081101561074d57600080fd5b5080359060208101359060400135611df0565b34801561076c57600080fd5b506103c9600480360361010081101561078457600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156107b457600080fd5b8201836020820111156107c657600080fd5b803590602001918460018302840111640100000000831117156107e857600080fd5b91935091508035906020810135906040810135906060810135906080013561208f565b34801561081757600080fd5b5061038d6004803603602081101561082e57600080fd5b5035612135565b34801561084157600080fd5b5061038d61216b565b34801561085657600080fd5b5061038d6004803603604081101561086d57600080fd5b506001600160a01b038135169060200135612171565b34801561088f57600080fd5b5061038d600480360360408110156108a657600080fd5b506001600160a01b0381351690602001356121af565b3480156108c857600080fd5b506103c96121f0565b3480156108dd57600080fd5b5061040a600480360360208110156108f457600080fd5b50356001600160a01b03166122ab565b34801561091057600080fd5b506103c96004803603604081101561092757600080fd5b506001600160a01b0381351690602001356122c6565b34801561094957600080fd5b5061038d61240b565b34801561095e57600080fd5b5061038d612415565b34801561097357600080fd5b506109916004803603602081101561098a57600080fd5b503561241b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156109cb5781810151838201526020016109b3565b50505050905090810190601f1680156109f85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610a1257600080fd5b5061040a6124d4565b348015610a2757600080fd5b5061038d6124e3565b348015610a3c57600080fd5b506103c960048036036040811015610a5357600080fd5b506001600160a01b0381351690602001356124e9565b348015610a7557600080fd5b5061040a612544565b348015610a8a57600080fd5b50610a93612553565b604080519115158252519081900360200190f35b348015610ab357600080fd5b506103c960048036036020811015610aca57600080fd5b5035612564565b348015610add57600080fd5b50610b0a60048036036040811015610af457600080fd5b506001600160a01b0381351690602001356125c9565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6103c960048036036020811015610b4657600080fd5b50356125fb565b348015610b5957600080fd5b50610b8c60048036036060811015610b7057600080fd5b506001600160a01b038135169060208101359060400135612606565b6040805192835260208301919091528051918290030190f35b6103c960048036036020811015610bbb57600080fd5b810190602081018135640100000000811115610bd657600080fd5b820183602082011115610be857600080fd5b80359060200191846001830284011164010000000083111715610c0a57600080fd5b50909250905061264d565b348015610c2157600080fd5b5061038d60048036036040811015610c3857600080fd5b506001600160a01b038135169060200135612886565b348015610c5a57600080fd5b50610c7860048036036020811015610c7157600080fd5b50356128a3565b604080519788526020880196909652868601949094526060860192909252608085015260a08401526001600160a01b031660c0830152519081900360e00190f35b348015610cc557600080fd5b5061057860048036036040811015610cdc57600080fd5b506001600160a01b0381351690602001356128e9565b348015610cfe57600080fd5b506103c960048036036060811015610d1557600080fd5b5080359060208101359060400135612915565b348015610d3457600080fd5b50610a9360048036036020811015610d4b57600080fd5b503561297f565b348015610d5e57600080fd5b5061040a612996565b348015610d7357600080fd5b5061038d60048036036020811015610d8a57600080fd5b50356129a5565b348015610d9d57600080fd5b5061038d6129b7565b348015610db257600080fd5b506103c960048036036040811015610dc957600080fd5b508035906020013515156129bd565b348015610de457600080fd5b5061038d60048036036040811015610dfb57600080fd5b506001600160a01b038135169060200135612bf5565b348015610e1d57600080fd5b50610a9360048036036040811015610e3457600080fd5b506001600160a01b038135169060200135612c12565b348015610e5657600080fd5b5061038d612ca8565b348015610e6b57600080fd5b506103c960048036036060811015610e8257600080fd5b5080359060208101359060400135612cae565b348015610ea157600080fd5b5061040a612d6b565b348015610eb657600080fd5b506103c960048036036020811015610ecd57600080fd5b50356001600160a01b0316612d7a565b60696020526000908152604090205481565b33610ef8615c05565b610f028284612ddc565b60208101518151919250600091610f1e9163ffffffff612f3c16565b9050610f418385610f3c856040015185612f3c90919063ffffffff16565b612f96565b6001600160a01b0383166000818152607360209081526040808320888452825291829020805485019055845185820151868401518451928352928201528083019190915290518692917f4119153d17a36f9597d40e3ab4148d03261a439dddbec4e91799ab7159608e26919081900360600190a350505050565b33610fc4615c05565b610fce8284612ddc565b90506000610fdb836130a2565b6001600160a01b0316611013836040015161100785602001518660000151612f3c90919063ffffffff16565b9063ffffffff612f3c16565b604051600081818185875af1925050503d806000811461104f576040519150601f19603f3d011682016040523d82523d6000602084013e611054565b606091505b50509050806110aa576040805162461bcd60e51b815260206004820152601260248201527f4661696c656420746f2073656e642046544d0000000000000000000000000000604482015290519081900360640190fd5b83836001600160a01b03167fc1d8eb6e444b89fb8ff0991c19311c070df704ccb009e210d1462d5b2410bf4584600001518560200151866040015160405180848152602001838152602001828152602001935050505060405180910390a350505050565b607b546001600160a01b031681565b60006111298383612c12565b61115757506001600160a01b03821660009081526072602090815260408083208484529091529020546111a0565b6001600160a01b03831660008181526073602090815260408083208684528252808320549383526072825280832086845290915290205461119d9163ffffffff6130c716565b90505b92915050565b60765481565b6111b533613109565b6111f05760405162461bcd60e51b8152600401808060200182810382526029815260200180615ce56029913960400191505060405180910390fd5b6111fd898989600061311d565b6001600160a01b0389166000908152606f602090815260408083208b8452909152902060020181905561122f876132b5565b851561130357868611156112745760405162461bcd60e51b815260040180806020018281038252602c815260200180615e05602c913960400191505060405180910390fd5b6001600160a01b03891660008181526073602090815260408083208c845282528083208a8155600181018a90556002810189905560038101889055848452607483528184208d855283529281902086905580518781529182018a9052805192938c9390927f138940e95abffcd789b497bf6188bba3afa5fbd22fb5c42c2f6018d1bf0f4e7892908290030190a3505b505050505050505050565b33600081815260736020908152604080832086845290915281209091908361137d576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b6113878286612c12565b6113d8576040805162461bcd60e51b815260206004820152600d60248201527f6e6f74206c6f636b656420757000000000000000000000000000000000000000604482015290519081900360640190fd5b805484111561142e576040805162461bcd60e51b815260206004820152601760248201527f6e6f7420656e6f756768206c6f636b6564207374616b65000000000000000000604482015290519081900360640190fd5b6114388286613353565b611489576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b6114928261340e565b156114e4576040805162461bcd60e51b815260206004820152600a60248201527f7265646972656374656400000000000000000000000000000000000000000000604482015290519081900360640190fd5b6114ee828661348c565b5060006115018387878560000154613661565b90508481111561150e5750835b8154859003825580156115815761152b838783600160008061368e565b607f546040516001600160a01b03909116908290600081818185875af1925050503d8060008114611578576040519150601f19603f3d011682016040523d82523d6000602084013e61157d565b606091505b5050505b85836001600160a01b03167fef6c0c14fe9aa51af36acd791464dec3badbde668b63189b47bfa4e25be9b2b98784604051808381526020018281526020019250505060405180910390a395945050505050565b6115dd33613109565b6116185760405162461bcd60e51b8152600401808060200182810382526029815260200180615ce56029913960400191505060405180910390fd5b8061166a576040805162461bcd60e51b815260206004820152600c60248201527f77726f6e67207374617475730000000000000000000000000000000000000000604482015290519081900360640190fd5b61167482826138b4565b61167f8260006129bd565b6000828152606860205260408120600601546001600160a01b0316906116a890829081906139de565b505050565b607160209081526000938452604080852082529284528284209052825290208054600182015460029092015490919083565b608254604080516001600160a01b03878116602483015286811660448084019190915283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4a7702bb000000000000000000000000000000000000000000000000000000001781529251825160009592909216938693928291908083835b602083106117ae57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611771565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114611811576040519150601f19603f3d011682016040523d82523d6000602084013e611816565b606091505b505090508080611824575082155b611875576040805162461bcd60e51b815260206004820152601b60248201527f676f7620766f746573207265636f756e74696e67206661696c65640000000000604482015290519081900360640190fd5b5050505050565b606d5481565b607760205280600052604060002060009150905080600701549080600801549080600901549080600a01549080600b01549080600c01549080600d0154905087565b6083546001600160a01b03163314611923576040805162461bcd60e51b815260206004820152601260248201527f6e6f74207346544d2066696e616c697a65720000000000000000000000000000604482015290519081900360640190fd5b61192d838361348c565b5060008111611983576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b607b54604080517f63d2bde50000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0386811660248301526044820186905260648201859052915191909216916363d2bde591608480830192600092919082900301818387803b1580156119fe57600080fd5b505af1158015611a12573d6000803e3d6000fd5b505050506001600160a01b0383166000908152607260209081526040808320858452909152902054811115611a8e576040805162461bcd60e51b815260206004820152601060248201527f6e6f7420656e6f756768207374616b6500000000000000000000000000000000604482015290519081900360640190fd5b6000611a9a848461111d565b905080821115611b29576001600160a01b038416600090815260736020908152604080832086845290915290208054611adb9083850363ffffffff6130c716565b815560408051838503815260006020820152815186926001600160a01b038916927fef6c0c14fe9aa51af36acd791464dec3badbde668b63189b47bfa4e25be9b2b9929081900390910190a3505b611b3a84848460006001600061368e565b611b458360006129bd565b64ffffffffff83856001600160a01b03167fd3bb4e423fbea695d16b982f9f682dc5f35152e5411646a8a5a79a6b02ba8d57856040518082815260200191505060405180910390a4604051600090339084908381818185875af1925050503d8060008114611bcf576040519150601f19603f3d011682016040523d82523d6000602084013e611bd4565b606091505b5050905080611c2a576040805162461bcd60e51b815260206004820152601260248201527f4661696c656420746f2073656e642046544d0000000000000000000000000000604482015290519081900360640190fd5b64ffffffffff84866001600160a01b03167f75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21866040518082815260200191505060405180910390a45050505050565b611c8d338383611c88336130a2565b613b88565b5050565b6088602052600090815260409020546001600160a01b031681565b611cb4612553565b611d05576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611d0e8261297f565b611d5f576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f722069736e277420736c6173686564000000000000000000604482015290519081900360640190fd5b611d67614098565b811115611da55760405162461bcd60e51b8152600401808060200182810382526021815260200180615dbb6021913960400191505060405180910390fd5b6000828152607a60209081526040918290208390558151838152915184927f047575f43f09a7a093d94ec483064acfc61b7e25c0de28017da442abf99cb91792908290030190a25050565b33611dfb818561348c565b5060008211611e51576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e5b818561111d565b821115611eaf576040805162461bcd60e51b815260206004820152601960248201527f6e6f7420656e6f75676820756e6c6f636b6564207374616b6500000000000000604482015290519081900360640190fd5b611eb98185613353565b611f0a576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152607160209081526040808320878452825280832086845290915290206002015415611f8b576040805162461bcd60e51b815260206004820152601360248201527f7772494420616c72656164792065786973747300000000000000000000000000604482015290519081900360640190fd5b611f9c81858460016000600161368e565b6001600160a01b038116600090815260716020908152604080832087845282528083208684529091529020600201829055611fd561240b565b6001600160a01b038216600090815260716020908152604080832088845282528083208784529091529020556120096140a4565b6001600160a01b038216600090815260716020908152604080832088845282528083208784529091528120600101919091556120469085906129bd565b8284826001600160a01b03167fd3bb4e423fbea695d16b982f9f682dc5f35152e5411646a8a5a79a6b02ba8d57856040518082815260200191505060405180910390a450505050565b61209833613109565b6120d35760405162461bcd60e51b8152600401808060200182810382526029815260200180615ce56029913960400191505060405180910390fd5b61211b898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915089905088886140a8565b606b5488111561130357606b889055505050505050505050565b6000818152606860209081526040808320600601546001600160a01b03168352607282528083208484529091529020545b919050565b606e5481565b600061217b615c05565b6121858484614285565b8051602082015160408301519293506121a7926110079163ffffffff612f3c16565b949350505050565b60006121bb8383612c12565b6121c7575060006111a0565b506001600160a01b03919091166000908152607360209081526040808320938352929052205490565b6121f8612553565b612249576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6089602052600090815260409020546001600160a01b031681565b6001600160a01b03821660009081526084602090815260408083208484529091528120905b8154811015612405576122fc6140a4565b82828154811061230857fe5b9060005260206000209060020201600101541080612343575081818154811061232d57fe5b9060005260206000209060020201600001546000145b156123fc57815482907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061237857fe5b906000526020600020906002020182828154811061239257fe5b60009182526020909120825460029092020190815560019182015491015581548290806123bb57fe5b60008281526020812060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90930192830201818155600101559055612400565b6001015b6122eb565b50505050565b6067546001015b90565b60675481565b606a6020908152600091825260409182902080548351601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600186161502019093169290920491820184900484028101840190945280845290918301828280156124cc5780601f106124a1576101008083540402835291602001916124cc565b820191906000526020600020905b8154815290600101906020018083116124af57829003601f168201915b505050505081565b6082546001600160a01b031681565b606c5481565b6124f3828261348c565b611c8d576040805162461bcd60e51b815260206004820152601060248201527f6e6f7468696e6720746f20737461736800000000000000000000000000000000604482015290519081900360640190fd5b6033546001600160a01b031690565b6033546001600160a01b0316331490565b61256c612553565b6125bd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6125c6816142f3565b50565b607360209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b6125c6338234612f96565b6084602052826000526040600020602052816000526040600020818154811061262b57fe5b6000918252602090912060029091020180546001909101549093509150839050565b608160009054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561269b57600080fd5b505afa1580156126af573d6000803e3d6000fd5b505050506040513d60208110156126c557600080fd5b505134101561271b576040805162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742073656c662d7374616b65000000000000000000604482015290519081900360640190fd5b60428114801561276657508181600081811061273357fe5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660c060f81b145b6127b7576040805162461bcd60e51b815260206004820152601060248201527f6d616c666f726d6564207075626b657900000000000000000000000000000000604482015290519081900360640190fd5b60866000838360405180838380828437604080519190930181900390208652506020850195909552505050016000205415612839576040805162461bcd60e51b815260206004820152600c60248201527f616c726561647920757365640000000000000000000000000000000000000000604482015290519081900360640190fd5b6128793383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061435d92505050565b611c8d33606b5434612f96565b607060209081526000928352604080842090915290825290205481565b606860205260009081526040902080546001820154600283015460038401546004850154600586015460069096015494959394929391929091906001600160a01b031687565b607460209081526000928352604080842090915290825290208054600182015460029092015490919083565b336129208185612c12565b612971576040805162461bcd60e51b815260206004820152600d60248201527f6e6f74206c6f636b656420757000000000000000000000000000000000000000604482015290519081900360640190fd5b612405818585856001614388565b600090815260686020526040902054608016151590565b607f546001600160a01b031681565b607a6020526000908152604090205481565b606b5481565b6129c6826148e5565b612a17576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f7220646f65736e2774206578697374000000000000000000604482015290519081900360640190fd5b60008281526068602052604090206003810154905415612a35575060005b606654604080517fa4066fbe000000000000000000000000000000000000000000000000000000008152600481018690526024810184905290516001600160a01b039092169163a4066fbe9160448082019260009290919082900301818387803b158015612aa257600080fd5b505af1158015612ab6573d6000803e3d6000fd5b50505050818015612ac657508015155b156116a8576066546000848152606a60205260409081902081517f242a6e3f0000000000000000000000000000000000000000000000000000000081526004810187815260248201938452825460027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001831615610100020190911604604483018190526001600160a01b039095169463242a6e3f94899493909160649091019084908015612bb75780601f10612b8c57610100808354040283529160200191612bb7565b820191906000526020600020905b815481529060010190602001808311612b9a57829003601f168201915b50509350505050600060405180830381600087803b158015612bd857600080fd5b505af1158015612bec573d6000803e3d6000fd5b50505050505050565b607260209081526000928352604080842090915290825290205481565b6001600160a01b038216600090815260736020908152604080832084845290915281206002015415801590612c6957506001600160a01b038316600090815260736020908152604080832085845290915290205415155b801561119d57506001600160a01b0383166000908152607360209081526040808320858452909152902060020154612c9f6140a4565b11159392505050565b607e5481565b3381612d01576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b612d0b8185612c12565b15612d5d576040805162461bcd60e51b815260206004820152601160248201527f616c7265616479206c6f636b6564207570000000000000000000000000000000604482015290519081900360640190fd5b612405818585856000614388565b6087546001600160a01b031681565b612d82612553565b612dd3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6125c6816148fc565b612de4615c05565b612dee8383613353565b612e3f576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b612e49838361348c565b50506001600160a01b0382166000908152606f6020908152604080832084845282528083208151606081018352815480825260018301549482018590526002909201549281018390529392612ea7926110079163ffffffff612f3c16565b905080612efb576040805162461bcd60e51b815260206004820152600c60248201527f7a65726f20726577617264730000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0384166000908152606f6020908152604080832086845290915281208181556001810182905560020155612f35816132b5565b5092915050565b60008282018381101561119d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612f9f826148e5565b612ff0576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f7220646f65736e2774206578697374000000000000000000604482015290519081900360640190fd5b60008281526068602052604090205415613051576040805162461bcd60e51b815260206004820152601660248201527f76616c696461746f722069736e27742061637469766500000000000000000000604482015290519081900360640190fd5b61305e838383600161311d565b613067826149b5565b6116a85760405162461bcd60e51b8152600401808060200182810382526029815260200180615ddc6029913960400191505060405180910390fd5b6000806130ae83614a89565b90506001600160a01b0381166111a05782915050612166565b600061119d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b1c565b6066546001600160a01b0390811691161490565b60008211613172576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b61317c848461348c565b506001600160a01b03841660009081526072602090815260408083208684529091529020546131b1908363ffffffff612f3c16565b6001600160a01b03851660009081526072602090815260408083208784528252808320939093556068905220600301546131f1818463ffffffff612f3c16565b600085815260686020526040902060030155606c54613216908463ffffffff612f3c16565b606c5560008481526068602052604090205461324357606d5461323f908463ffffffff612f3c16565b606d555b61324e8482156129bd565b60408051848152905185916001600160a01b038816917f9a8f44850296624dadfd9c246d17e47171d35727a181bd090aa14bbbe00238bb9181900360200190a36000848152606860205260409020600601546118759086906001600160a01b0316846139de565b606654604080517f66e7ea0f0000000000000000000000000000000000000000000000000000000081523060048201526024810184905290516001600160a01b03909216916366e7ea0f9160448082019260009290919082900301818387803b15801561332157600080fd5b505af1158015613335573d6000803e3d6000fd5b505060765461334d925090508263ffffffff612f3c16565b60765550565b607b546000906001600160a01b031661336e575060016111a0565b607b54604080517f21d585c30000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260248201869052915191909216916321d585c3916044808301926020929190829003018186803b1580156133db57600080fd5b505afa1580156133ef573d6000803e3d6000fd5b505050506040513d602081101561340557600080fd5b50519392505050565b6000606061341a614bb8565b50905060005b81518110156134695781818151811061343557fe5b60200260200101516001600160a01b0316846001600160a01b0316141561346157600192505050612166565b600101613420565b5050506001600160a01b0390811660009081526089602052604090205416151590565b6000613496615c05565b6134a08484614ea3565b90506134ab83614fdb565b6001600160a01b0385166000818152607060209081526040808320888452825280832094909455918152606f8252828120868252825282902082516060810184528154815260018201549281019290925260020154918101919091526135119082615036565b6001600160a01b0385166000818152606f602090815260408083208884528252808320855181558583015160018083019190915595820151600291820155938352607482528083208884528252918290208251606081018452815481529481015491850191909152909101549082015261358b9082615036565b6001600160a01b0385166000908152607460209081526040808320878452825291829020835181559083015160018201559101516002909101556135cf8484612c12565b613632576001600160a01b0384166000818152607360209081526040808320878452825280832083815560018082018590556002808301869055600390920185905594845260748352818420888552909252822082815592830182905591909101555b61363c84846150a8565b602081015115158061364e5750805115155b806121a757506040015115159392505050565b600080613670868686866153bb565b905060006136808787878761545a565b919091019695505050505050565b6001600160a01b038616600090815260726020908152604080832088845282528083208054889003905560689091529020600301546136d3908563ffffffff6130c716565b600086815260686020526040902060030155606c546136f8908563ffffffff6130c716565b606c5560008581526068602052604090205461372557606d54613721908563ffffffff6130c716565b606d555b600061373086612135565b9050801580159061374d5750600086815260686020526040902054155b1561388257608160009054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156137a057600080fd5b505afa1580156137b4573d6000803e3d6000fd5b505050506040513d60208110156137ca57600080fd5b5051811015613831578215613826576040805162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742073656c662d7374616b65000000000000000000604482015290519081900360640190fd5b6138318660016138b4565b8115806138425750613842866149b5565b61387d5760405162461bcd60e51b8152600401808060200182810382526029815260200180615ddc6029913960400191505060405180910390fd5b61388d565b61388d8660016138b4565b600086815260686020526040902060060154612bec9088906001600160a01b0316866139de565b6000828152606860205260409020541580156138cf57508015155b156138fc57600082815260686020526040902060030154606d546138f89163ffffffff6130c716565b606d555b600082815260686020526040902054811115611c8d576000828152606860205260409020818155600201546139a45761393361240b565b60008381526068602052604090206002015561394d6140a4565b6000838152606860209081526040918290206001810184905560020154825190815290810192909252805184927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e4792908290030190a25b60408051828152905183917fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e919081900360200190a25050565b6082546001600160a01b0316156116a857608254604080516001600160a01b03868116602483015285811660448084019190915283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4a7702bb00000000000000000000000000000000000000000000000000000000178152925182516000959290921693627a120093928291908083835b60208310613ac157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613a84565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114613b24576040519150601f19603f3d011682016040523d82523d6000602084013e613b29565b606091505b505090508080613b37575081155b612405576040805162461bcd60e51b815260206004820152601b60248201527f676f7620766f746573207265636f756e74696e67206661696c65640000000000604482015290519081900360640190fd5b613b90615c05565b506001600160a01b038416600090815260716020908152604080832086845282528083208584528252918290208251606081018452815480825260018301549382019390935260029091015492810192909252613c34576040805162461bcd60e51b815260206004820152601560248201527f7265717565737420646f65736e27742065786973740000000000000000000000604482015290519081900360640190fd5b613c3e8585613353565b613c8f576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b60208082015182516000878152606890935260409092206001015490919015801590613ccb575060008681526068602052604090206001015482115b15613cec575050600084815260686020526040902060018101546002909101545b608160009054906101000a90046001600160a01b03166001600160a01b031663b82b84276040518163ffffffff1660e01b815260040160206040518083038186803b158015613d3a57600080fd5b505afa158015613d4e573d6000803e3d6000fd5b505050506040513d6020811015613d6457600080fd5b50518201613d706140a4565b1015613dc3576040805162461bcd60e51b815260206004820152601660248201527f6e6f7420656e6f7567682074696d652070617373656400000000000000000000604482015290519081900360640190fd5b608160009054906101000a90046001600160a01b03166001600160a01b031663650acd666040518163ffffffff1660e01b815260040160206040518083038186803b158015613e1157600080fd5b505afa158015613e25573d6000803e3d6000fd5b505050506040513d6020811015613e3b57600080fd5b50518101613e4761240b565b1015613e9a576040805162461bcd60e51b815260206004820152601860248201527f6e6f7420656e6f7567682065706f636873207061737365640000000000000000604482015290519081900360640190fd5b6001600160a01b0387166000908152607160209081526040808320898452825280832088845290915281206002015490613ed38861297f565b90506000613ef58383607a60008d81526020019081526020016000205461553a565b6001600160a01b038b1660009081526071602090815260408083208d845282528083208c845290915281208181556001810182905560020155606e8054820190559050808311613f8c576040805162461bcd60e51b815260206004820152601660248201527f7374616b652069732066756c6c7920736c617368656400000000000000000000604482015290519081900360640190fd5b60006001600160a01b038816613fa8858463ffffffff6130c716565b604051600081818185875af1925050503d8060008114613fe4576040519150601f19603f3d011682016040523d82523d6000602084013e613fe9565b606091505b505090508061403f576040805162461bcd60e51b815260206004820152601260248201527f4661696c656420746f2073656e642046544d0000000000000000000000000000604482015290519081900360640190fd5b614048826142f3565b888a8c6001600160a01b03167f75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21876040518082815260200191505060405180910390a45050505050505050505050565b670de0b6b3a764000090565b4290565b6001600160a01b03881660009081526069602052604090205415614113576040805162461bcd60e51b815260206004820152601860248201527f76616c696461746f7220616c7265616479206578697374730000000000000000604482015290519081900360640190fd5b6001600160a01b03881660008181526069602090815260408083208b90558a8352606882528083208981556004810189905560058101889055600181018690556002810187905560060180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909417909355606a8152919020875161419c92890190615c26565b508551602080880191909120600090815260868252604090819020899055805186815291820185905280516001600160a01b038b16928a927f49bca1ed2666922f9f1690c26a569e1299c2a715fe57647d77e81adfabbf25bf92918290030190a3811561423e576040805183815260208101839052815189927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e47928290030190a25b841561427b5760408051868152905188917fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e919081900360200190a25b5050505050505050565b61428d615c05565b614295615c05565b61429f8484614ea3565b6001600160a01b0385166000908152606f6020908152604080832087845282529182902082516060810184528154815260018201549281019290925260020154918101919091529091506121a79082615036565b80156125c65760405160009082156108fc0290839083818181858288f19350505050158015614326573d6000803e3d6000fd5b506040805182815290517f8918bd6046d08b314e457977f29562c5d76a7030d79b1edba66e8a5da0b77ae89181900360200190a150565b606b8054600101908190556116a8838284600061437861240b565b6143806140a4565b6000806140a8565b6143918561340e565b156143e3576040805162461bcd60e51b815260206004820152600a60248201527f7265646972656374656400000000000000000000000000000000000000000000604482015290519081900360640190fd5b6143ed858561111d565b821115614441576040805162461bcd60e51b815260206004820152601060248201527f6e6f7420656e6f756768207374616b6500000000000000000000000000000000604482015290519081900360640190fd5b600084815260686020526040902054156144a2576040805162461bcd60e51b815260206004820152601660248201527f76616c696461746f722069736e27742061637469766500000000000000000000604482015290519081900360640190fd5b608160009054906101000a90046001600160a01b03166001600160a01b0316630d7b26096040518163ffffffff1660e01b815260040160206040518083038186803b1580156144f057600080fd5b505afa158015614504573d6000803e3d6000fd5b505050506040513d602081101561451a57600080fd5b505183108015906145a45750608160009054906101000a90046001600160a01b03166001600160a01b0316630d4955e36040518163ffffffff1660e01b815260040160206040518083038186803b15801561457457600080fd5b505afa158015614588573d6000803e3d6000fd5b505050506040513d602081101561459e57600080fd5b50518311155b6145f5576040805162461bcd60e51b815260206004820152601260248201527f696e636f7272656374206475726174696f6e0000000000000000000000000000604482015290519081900360640190fd5b6000614603846110076140a4565b6000868152606860205260409020600601549091506001600160a01b039081169087168114614696576001600160a01b038116600090815260736020908152604080832089845290915290206002015462278d00018211156146965760405162461bcd60e51b8152600401808060200182810382526025815260200180615d0e6025913960400191505060405180910390fd5b6146a0878761348c565b506146ab87876122c6565b6001600160a01b03871660009081526073602090815260408083208984529091529020831561480b576001600160a01b03881660009081526084602090815260408083208a84529091528120825490919061470a908b908b90806153bb565b905080156148085760408051808201909152818152600280850154602080840191825285546001818101885560008881529290922094519302909301918255519101558154601e10156147a4576040805162461bcd60e51b815260206004820152601860248201527f746f6f206d616e79206f6e676f696e672072656c6f636b730000000000000000604482015290519081900360640190fd5b8254606490048711806147b957508154600310155b806147cd5750826002015462127500018510155b6148085760405162461bcd60e51b8152600401808060200182810382526067815260200180615d546067913960800191505060405180910390fd5b50505b8060030154861015614864576040805162461bcd60e51b815260206004820152601f60248201527f6c6f636b7570206475726174696f6e2063616e6e6f7420646563726561736500604482015290519081900360640190fd5b8054614876908663ffffffff612f3c16565b815561488061240b565b600182015560028101839055600381018690556040805187815260208101879052815189926001600160a01b038c16927f138940e95abffcd789b497bf6188bba3afa5fbd22fb5c42c2f6018d1bf0f4e78929081900390910190a35050505050505050565b600090815260686020526040902060050154151590565b6001600160a01b0381166149415760405162461bcd60e51b8152600401808060200182810382526026815260200180615cbf6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000614a6e6149c2614098565b608154604080517f2265f2840000000000000000000000000000000000000000000000000000000081529051614a62926001600160a01b031691632265f284916004808301926020929190829003018186803b158015614a2157600080fd5b505afa158015614a35573d6000803e3d6000fd5b505050506040513d6020811015614a4b57600080fd5b5051614a5686612135565b9063ffffffff61559916565b9063ffffffff6155f216565b60008381526068602052604090206003015411159050919050565b6000606080614a96614bb8565b909250905060005b8251811015614afa57828181518110614ab357fe5b60200260200101516001600160a01b0316856001600160a01b03161415614af257818181518110614ae057fe5b60200260200101519350505050612166565b600101614a9e565b505050506001600160a01b039081166000908152608960205260409020541690565b60008184841115614bab5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614b70578181015183820152602001614b58565b50505050905090810190601f168015614b9d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50508183035b9392505050565b60408051600580825260c08201909252606091829182916020820160a080388339505060408051600580825260c0820190925292935060609291506020820160a0803883390190505090508051825114614c0e57fe5b7393419fcb5d9dc7989439f0512d4f737421ed48d982600081518110614c3057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507380f93310709624636852d0111fd6c4a6e02ed0aa81600081518110614c7257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073fbcae1b28ca5039dafec4f10a89e022bc811839482600181518110614cb457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507391b20102dfd2ff1b00d0915266584009d0b1ae3981600181518110614cf657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507315c2ec517905fb3282f26f3ac3e12889755a2ed782600281518110614d3857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073ca3c54c11172a7263300a801e9937780b5143c0881600281518110614d7a57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073bdaaec5f9317cc63d26fd7d79ad17372ccd7d76382600381518110614dbc57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050735a1cad027eace4c052f5dee0f42da6c62e39b77981600381518110614dfe57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073f72148504819a1d1b038694b02d299f65bfa312d82600481518110614e4057fe5b60200260200101906001600160a01b031690816001600160a01b031681525050734a15b527475977d9b0cb3fcfe825d6aa7428fafc81600481518110614e8257fe5b6001600160a01b039092166020928302919091019091015290925090509091565b614eab615c05565b6001600160a01b038316600090815260706020908152604080832085845290915281205490614ed984614fdb565b90506000614ee78686615634565b905081811115614ef45750805b82811015614eff5750815b6001600160a01b03861660008181526073602090815260408083208984528252808320938352607282528083208984529091528120548254909190614f4b90839063ffffffff6130c716565b90506000614f5f84600001548a8988615711565b9050614f69615c05565b614f7782866003015461577f565b9050614f85838b8a89615711565b9150614f8f615c05565b614f9a83600061577f565b9050614fa8858c898b615711565b9250614fb2615c05565b614fbd84600061577f565b9050614fca838383615940565b9d9c50505050505050505050505050565b6000818152606860205260408120600201541561502e5760008281526068602052604090206002015460675410156150165750606754612166565b50600081815260686020526040902060020154612166565b505060675490565b61503e615c05565b604080516060810190915282518451829161505f919063ffffffff612f3c16565b815260200161507f84602001518660200151612f3c90919063ffffffff16565b815260200161509f84604001518660400151612f3c90919063ffffffff16565b90529392505050565b6001600160a01b0382166000908152607460209081526040808320848452909152902060018101548154600290910401806150e4575050611c8d565b6001600160a01b0384166000908152607360209081526040808320868452909152812060038101548154919290919061511c8361595b565b90508061512e57505050505050611c8d565b600061514784614a62637cbe4cbf614a568c89886159e1565b6001600160a01b038a1660009081526072602090815260408083208c845290915281205491925061522b615179614098565b614a6261520d608160009054906101000a90046001600160a01b03166001600160a01b031663a77865156040518163ffffffff1660e01b815260040160206040518083038186803b1580156151cd57600080fd5b505afa1580156151e1573d6000803e3d6000fd5b505050506040513d60208110156151f757600080fd5b5051615201614098565b9063ffffffff6130c716565b614a56670de0b6b3a7640000614a628c838a8c63ffffffff61559916565b60008b8152606860205260409020600601549091506001600160a01b038c81169116141561532657600061526a600a614a62600b614a568f8c8b615a92565b9050615320615277614098565b608154604080517fa77865150000000000000000000000000000000000000000000000000000000081529051614a62926001600160a01b03169163a7786515916004808301926020929190829003018186803b1580156152d657600080fd5b505afa1580156152ea573d6000803e3d6000fd5b505050506040513d602081101561530057600080fd5b5051614a56670de0b6b3a7640000614a628d83898d63ffffffff61559916565b82019150505b61533a82614a62838863ffffffff61559916565b9050615344615c05565b61534e828861577f565b905060008160000151600283602001518161536557fe5b04019050808a11156153ac578a54615389908b90614a62908463ffffffff61559916565b8b5560018b01546153a6908b90614a62908463ffffffff61559916565b60018c01555b50505050505050505050505050565b6001600160a01b03841660009081526074602090815260408083208684529091528120805482906153f8908590614a62908863ffffffff61559916565b9050600061541785614a6288866001015461559990919063ffffffff16565b83549091506002820483019061542d90846130c7565b84556001840154615444908363ffffffff6130c716565b6001909401939093555090915050949350505050565b600061546685856122c6565b6001600160a01b0385166000908152608460209081526040808320878452909152812090805b825481101561552f5760006154c886614a62898786815481106154ab57fe5b60009182526020909120600290910201549063ffffffff61559916565b90506154f7818584815481106154da57fe5b60009182526020909120600290910201549063ffffffff6130c716565b84838154811061550357fe5b6000918252602090912060029091020155615524838263ffffffff612f3c16565b92505060010161548c565b509695505050505050565b6000821580615550575061554c614098565b8210155b1561555d57506000614bb1565b615588600161100761556d614098565b614a6286615579614098565b8a91900363ffffffff61559916565b905083811115614bb1575082614bb1565b6000826155a8575060006111a0565b828202828482816155b557fe5b041461119d5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d336021913960400191505060405180910390fd5b600061119d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250615b2a565b6001600160a01b0382166000908152607360209081526040808320848452909152812060010154606754615669858583615b85565b156156775791506111a09050565b615682858584615b85565b615691576000925050506111a0565b808211156156a4576000925050506111a0565b808210156156d7576002818301046156bd868683615b85565b156156cd578060010192506156d1565b8091505b506156a4565b806156e7576000925050506111a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01949350505050565b6000818310615722575060006121a7565b600083815260776020818152604080842088855260019081018352818520548786529383528185208986520190915290912054615774615760614098565b614a6289614a56858763ffffffff6130c716565b979650505050505050565b615787615c05565b60405180606001604052806000815260200160008152602001600081525090506000608160009054906101000a90046001600160a01b03166001600160a01b0316635e2308d26040518163ffffffff1660e01b815260040160206040518083038186803b1580156157f757600080fd5b505afa15801561580b573d6000803e3d6000fd5b505050506040513d602081101561582157600080fd5b50519050821561591957600081615836614098565b03905060006158c8608160009054906101000a90046001600160a01b03166001600160a01b0316630d4955e36040518163ffffffff1660e01b815260040160206040518083038186803b15801561588c57600080fd5b505afa1580156158a0573d6000803e3d6000fd5b505050506040513d60208110156158b657600080fd5b5051614a62848863ffffffff61559916565b905060006158e96158d7614098565b614a628987860163ffffffff61559916565b90506159066158f6614098565b614a62898763ffffffff61559916565b602086018190529003845250612f359050565b615934615924614098565b614a62868463ffffffff61559916565b60408301525092915050565b615948615c05565b6121a76159558585615036565b83615036565b60008060056067548161596a57fe5b04905061271081111561597c57506127105b60675481900360009081526077602052604090206007015480158061599f575081155b156159af57600092505050612166565b6000826159be836152016140a4565b816159c557fe5b04905080600f0260010185816159d757fe5b0495945050505050565b6000806159f0846152016140a4565b9050600080805b601e8111615a745760675481870290036000818152607760205260409020600781015486811015615a415760028411615a395789975050505050505050614bb1565b505050615a74565b60008b81526002830160205260409020548015615a645795508585615a64578095505b5050600190920191506159f79050565b50818103600560048802048111156157745786945050505050614bb1565b600083815260686020526040812060030154600182615ab3866152016140a4565b905060015b601e8111615b1457606754818702900360008181526077602052604090206007810154841115615ae9575050615b14565b60008a8152602082905260409020548015615b0957958601956001909501945b505050600101615ab8565b50818381615b1e57fe5b04979650505050505050565b60008183615b795760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b70578181015183820152602001614b58565b5060008385816159d757fe5b6001600160a01b038316600090815260736020908152604080832085845290915281206001015482108015906121a757506001600160a01b0384166000908152607360209081526040808320868452909152902060020154615be683615bf0565b1115949350505050565b60009081526077602052604090206007015490565b60405180606001604052806000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c6757805160ff1916838001178555615c94565b82800160010185558215615c94579182015b82811115615c94578251825591602001919060010190615c79565b50615ca0929150615ca4565b5090565b61241291905b80821115615ca05760008155600101615caa56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737363616c6c6572206973206e6f7420746865204e6f64654472697665724175746820636f6e747261637476616c696461746f722773206c6f636b75702077696c6c20656e6420746f6f206561726c79536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746f6f206672657175656e742072656c6f636b7320286769746875622e636f6d2f46616e746f6d2d666f756e646174696f6e2f6f706572612d7366632f77696b692f4c6f636b75702d63616c6c732d7265666572656e63652372652d6c6f636b2d7374616b65296d757374206265206c657373207468616e206f7220657175616c20746f20312e3076616c696461746f7227732064656c65676174696f6e73206c696d69742069732065786365656465646c6f636b6564207374616b652069732067726561746572207468616e207468652077686f6c65207374616b65a265627a7a723158203c1c9de1f67b505472c83b4a1ca9bff66663f6574ecb9726a0763a868673bf8264736f6c63430005110032
Deployed Bytecode
0x6080604052600436106103555760003560e01c80637cacb1d6116101bb578063b5d89627116100f7578063cc8343aa11610095578063d96ed5051161006f578063d96ed50514610e4a578063de67f21514610e5f578063e9a505a714610e95578063f2fde38b14610eaa57610355565b8063cc8343aa14610da6578063cfd4766314610dd8578063cfdbb7cd14610e1157610355565b8063c3de580e116100d1578063c3de580e14610d28578063c5f956af14610d52578063c65ee0e114610d67578063c7be95de14610d9157610355565b8063b5d8962714610c4e578063b810e41114610cb9578063bd14d90714610cf257610355565b80638f32d59b116101645780639fa6dd351161013e5780639fa6dd3514610b30578063a45e115414610b4d578063a5a470ad14610ba5578063a86a056f14610c1557610355565b80638f32d59b14610a7e57806390a6c47514610aa757806396c7ee4614610ad157610355565b80638b0e9f3f116101955780638b0e9f3f14610a1b5780638cddb01514610a305780638da5cb5b14610a6957610355565b80637cacb1d614610952578063854873e114610967578063893675c614610a0657610355565b80633a488397116102955780635fab23a811610233578063715018a61161020d578063715018a6146108bc578063736de9ae146108d157806375dcf03014610904578063766718081461093d57610355565b80635fab23a8146108355780636099ecb21461084a578063670322f81461088357610355565b80634f7c4efb1161026f5780634f7c4efb146106fa5780634f864df41461072a5780634feb92f3146107605780635601fe011461080b57610355565b80633a48839714610658578063441a3e7014610697578063468f35ee146106c757610355565b806318f628d4116103025780631f270152116102dc5780631f2701521461053957806320c0849d1461059657806328f73148146105e157806339b80c00146105f657610355565b806318f628d4146104745780631d3ac42c146104d95780631e702f831461050957610355565b80630e559d82116103335780630e559d82146103f557806312622d0e1461042657806318160ddd1461045f57610355565b80630135b1db1461035a57806308c368741461039f5780630962ef79146103cb575b600080fd5b34801561036657600080fd5b5061038d6004803603602081101561037d57600080fd5b50356001600160a01b0316610edd565b60408051918252519081900360200190f35b3480156103ab57600080fd5b506103c9600480360360208110156103c257600080fd5b5035610eef565b005b3480156103d757600080fd5b506103c9600480360360208110156103ee57600080fd5b5035610fbb565b34801561040157600080fd5b5061040a61110e565b604080516001600160a01b039092168252519081900360200190f35b34801561043257600080fd5b5061038d6004803603604081101561044957600080fd5b506001600160a01b03813516906020013561111d565b34801561046b57600080fd5b5061038d6111a6565b34801561048057600080fd5b506103c9600480360361012081101561049857600080fd5b506001600160a01b038135169060208101359060408101359060608101359060808101359060a08101359060c08101359060e08101359061010001356111ac565b3480156104e557600080fd5b5061038d600480360360408110156104fc57600080fd5b508035906020013561130e565b34801561051557600080fd5b506103c96004803603604081101561052c57600080fd5b50803590602001356115d4565b34801561054557600080fd5b506105786004803603606081101561055c57600080fd5b506001600160a01b0381351690602081013590604001356116ad565b60408051938452602084019290925282820152519081900360600190f35b3480156105a257600080fd5b506103c9600480360360808110156105b957600080fd5b506001600160a01b0381358116916020810135909116906040810135151590606001356116df565b3480156105ed57600080fd5b5061038d61187c565b34801561060257600080fd5b506106206004803603602081101561061957600080fd5b5035611882565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b34801561066457600080fd5b506103c96004803603606081101561067b57600080fd5b506001600160a01b0381351690602081013590604001356118c4565b3480156106a357600080fd5b506103c9600480360360408110156106ba57600080fd5b5080359060200135611c79565b3480156106d357600080fd5b5061040a600480360360208110156106ea57600080fd5b50356001600160a01b0316611c91565b34801561070657600080fd5b506103c96004803603604081101561071d57600080fd5b5080359060200135611cac565b34801561073657600080fd5b506103c96004803603606081101561074d57600080fd5b5080359060208101359060400135611df0565b34801561076c57600080fd5b506103c9600480360361010081101561078457600080fd5b6001600160a01b03823516916020810135918101906060810160408201356401000000008111156107b457600080fd5b8201836020820111156107c657600080fd5b803590602001918460018302840111640100000000831117156107e857600080fd5b91935091508035906020810135906040810135906060810135906080013561208f565b34801561081757600080fd5b5061038d6004803603602081101561082e57600080fd5b5035612135565b34801561084157600080fd5b5061038d61216b565b34801561085657600080fd5b5061038d6004803603604081101561086d57600080fd5b506001600160a01b038135169060200135612171565b34801561088f57600080fd5b5061038d600480360360408110156108a657600080fd5b506001600160a01b0381351690602001356121af565b3480156108c857600080fd5b506103c96121f0565b3480156108dd57600080fd5b5061040a600480360360208110156108f457600080fd5b50356001600160a01b03166122ab565b34801561091057600080fd5b506103c96004803603604081101561092757600080fd5b506001600160a01b0381351690602001356122c6565b34801561094957600080fd5b5061038d61240b565b34801561095e57600080fd5b5061038d612415565b34801561097357600080fd5b506109916004803603602081101561098a57600080fd5b503561241b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156109cb5781810151838201526020016109b3565b50505050905090810190601f1680156109f85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610a1257600080fd5b5061040a6124d4565b348015610a2757600080fd5b5061038d6124e3565b348015610a3c57600080fd5b506103c960048036036040811015610a5357600080fd5b506001600160a01b0381351690602001356124e9565b348015610a7557600080fd5b5061040a612544565b348015610a8a57600080fd5b50610a93612553565b604080519115158252519081900360200190f35b348015610ab357600080fd5b506103c960048036036020811015610aca57600080fd5b5035612564565b348015610add57600080fd5b50610b0a60048036036040811015610af457600080fd5b506001600160a01b0381351690602001356125c9565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6103c960048036036020811015610b4657600080fd5b50356125fb565b348015610b5957600080fd5b50610b8c60048036036060811015610b7057600080fd5b506001600160a01b038135169060208101359060400135612606565b6040805192835260208301919091528051918290030190f35b6103c960048036036020811015610bbb57600080fd5b810190602081018135640100000000811115610bd657600080fd5b820183602082011115610be857600080fd5b80359060200191846001830284011164010000000083111715610c0a57600080fd5b50909250905061264d565b348015610c2157600080fd5b5061038d60048036036040811015610c3857600080fd5b506001600160a01b038135169060200135612886565b348015610c5a57600080fd5b50610c7860048036036020811015610c7157600080fd5b50356128a3565b604080519788526020880196909652868601949094526060860192909252608085015260a08401526001600160a01b031660c0830152519081900360e00190f35b348015610cc557600080fd5b5061057860048036036040811015610cdc57600080fd5b506001600160a01b0381351690602001356128e9565b348015610cfe57600080fd5b506103c960048036036060811015610d1557600080fd5b5080359060208101359060400135612915565b348015610d3457600080fd5b50610a9360048036036020811015610d4b57600080fd5b503561297f565b348015610d5e57600080fd5b5061040a612996565b348015610d7357600080fd5b5061038d60048036036020811015610d8a57600080fd5b50356129a5565b348015610d9d57600080fd5b5061038d6129b7565b348015610db257600080fd5b506103c960048036036040811015610dc957600080fd5b508035906020013515156129bd565b348015610de457600080fd5b5061038d60048036036040811015610dfb57600080fd5b506001600160a01b038135169060200135612bf5565b348015610e1d57600080fd5b50610a9360048036036040811015610e3457600080fd5b506001600160a01b038135169060200135612c12565b348015610e5657600080fd5b5061038d612ca8565b348015610e6b57600080fd5b506103c960048036036060811015610e8257600080fd5b5080359060208101359060400135612cae565b348015610ea157600080fd5b5061040a612d6b565b348015610eb657600080fd5b506103c960048036036020811015610ecd57600080fd5b50356001600160a01b0316612d7a565b60696020526000908152604090205481565b33610ef8615c05565b610f028284612ddc565b60208101518151919250600091610f1e9163ffffffff612f3c16565b9050610f418385610f3c856040015185612f3c90919063ffffffff16565b612f96565b6001600160a01b0383166000818152607360209081526040808320888452825291829020805485019055845185820151868401518451928352928201528083019190915290518692917f4119153d17a36f9597d40e3ab4148d03261a439dddbec4e91799ab7159608e26919081900360600190a350505050565b33610fc4615c05565b610fce8284612ddc565b90506000610fdb836130a2565b6001600160a01b0316611013836040015161100785602001518660000151612f3c90919063ffffffff16565b9063ffffffff612f3c16565b604051600081818185875af1925050503d806000811461104f576040519150601f19603f3d011682016040523d82523d6000602084013e611054565b606091505b50509050806110aa576040805162461bcd60e51b815260206004820152601260248201527f4661696c656420746f2073656e642046544d0000000000000000000000000000604482015290519081900360640190fd5b83836001600160a01b03167fc1d8eb6e444b89fb8ff0991c19311c070df704ccb009e210d1462d5b2410bf4584600001518560200151866040015160405180848152602001838152602001828152602001935050505060405180910390a350505050565b607b546001600160a01b031681565b60006111298383612c12565b61115757506001600160a01b03821660009081526072602090815260408083208484529091529020546111a0565b6001600160a01b03831660008181526073602090815260408083208684528252808320549383526072825280832086845290915290205461119d9163ffffffff6130c716565b90505b92915050565b60765481565b6111b533613109565b6111f05760405162461bcd60e51b8152600401808060200182810382526029815260200180615ce56029913960400191505060405180910390fd5b6111fd898989600061311d565b6001600160a01b0389166000908152606f602090815260408083208b8452909152902060020181905561122f876132b5565b851561130357868611156112745760405162461bcd60e51b815260040180806020018281038252602c815260200180615e05602c913960400191505060405180910390fd5b6001600160a01b03891660008181526073602090815260408083208c845282528083208a8155600181018a90556002810189905560038101889055848452607483528184208d855283529281902086905580518781529182018a9052805192938c9390927f138940e95abffcd789b497bf6188bba3afa5fbd22fb5c42c2f6018d1bf0f4e7892908290030190a3505b505050505050505050565b33600081815260736020908152604080832086845290915281209091908361137d576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b6113878286612c12565b6113d8576040805162461bcd60e51b815260206004820152600d60248201527f6e6f74206c6f636b656420757000000000000000000000000000000000000000604482015290519081900360640190fd5b805484111561142e576040805162461bcd60e51b815260206004820152601760248201527f6e6f7420656e6f756768206c6f636b6564207374616b65000000000000000000604482015290519081900360640190fd5b6114388286613353565b611489576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b6114928261340e565b156114e4576040805162461bcd60e51b815260206004820152600a60248201527f7265646972656374656400000000000000000000000000000000000000000000604482015290519081900360640190fd5b6114ee828661348c565b5060006115018387878560000154613661565b90508481111561150e5750835b8154859003825580156115815761152b838783600160008061368e565b607f546040516001600160a01b03909116908290600081818185875af1925050503d8060008114611578576040519150601f19603f3d011682016040523d82523d6000602084013e61157d565b606091505b5050505b85836001600160a01b03167fef6c0c14fe9aa51af36acd791464dec3badbde668b63189b47bfa4e25be9b2b98784604051808381526020018281526020019250505060405180910390a395945050505050565b6115dd33613109565b6116185760405162461bcd60e51b8152600401808060200182810382526029815260200180615ce56029913960400191505060405180910390fd5b8061166a576040805162461bcd60e51b815260206004820152600c60248201527f77726f6e67207374617475730000000000000000000000000000000000000000604482015290519081900360640190fd5b61167482826138b4565b61167f8260006129bd565b6000828152606860205260408120600601546001600160a01b0316906116a890829081906139de565b505050565b607160209081526000938452604080852082529284528284209052825290208054600182015460029092015490919083565b608254604080516001600160a01b03878116602483015286811660448084019190915283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4a7702bb000000000000000000000000000000000000000000000000000000001781529251825160009592909216938693928291908083835b602083106117ae57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611771565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114611811576040519150601f19603f3d011682016040523d82523d6000602084013e611816565b606091505b505090508080611824575082155b611875576040805162461bcd60e51b815260206004820152601b60248201527f676f7620766f746573207265636f756e74696e67206661696c65640000000000604482015290519081900360640190fd5b5050505050565b606d5481565b607760205280600052604060002060009150905080600701549080600801549080600901549080600a01549080600b01549080600c01549080600d0154905087565b6083546001600160a01b03163314611923576040805162461bcd60e51b815260206004820152601260248201527f6e6f74207346544d2066696e616c697a65720000000000000000000000000000604482015290519081900360640190fd5b61192d838361348c565b5060008111611983576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b607b54604080517f63d2bde50000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0386811660248301526044820186905260648201859052915191909216916363d2bde591608480830192600092919082900301818387803b1580156119fe57600080fd5b505af1158015611a12573d6000803e3d6000fd5b505050506001600160a01b0383166000908152607260209081526040808320858452909152902054811115611a8e576040805162461bcd60e51b815260206004820152601060248201527f6e6f7420656e6f756768207374616b6500000000000000000000000000000000604482015290519081900360640190fd5b6000611a9a848461111d565b905080821115611b29576001600160a01b038416600090815260736020908152604080832086845290915290208054611adb9083850363ffffffff6130c716565b815560408051838503815260006020820152815186926001600160a01b038916927fef6c0c14fe9aa51af36acd791464dec3badbde668b63189b47bfa4e25be9b2b9929081900390910190a3505b611b3a84848460006001600061368e565b611b458360006129bd565b64ffffffffff83856001600160a01b03167fd3bb4e423fbea695d16b982f9f682dc5f35152e5411646a8a5a79a6b02ba8d57856040518082815260200191505060405180910390a4604051600090339084908381818185875af1925050503d8060008114611bcf576040519150601f19603f3d011682016040523d82523d6000602084013e611bd4565b606091505b5050905080611c2a576040805162461bcd60e51b815260206004820152601260248201527f4661696c656420746f2073656e642046544d0000000000000000000000000000604482015290519081900360640190fd5b64ffffffffff84866001600160a01b03167f75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21866040518082815260200191505060405180910390a45050505050565b611c8d338383611c88336130a2565b613b88565b5050565b6088602052600090815260409020546001600160a01b031681565b611cb4612553565b611d05576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611d0e8261297f565b611d5f576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f722069736e277420736c6173686564000000000000000000604482015290519081900360640190fd5b611d67614098565b811115611da55760405162461bcd60e51b8152600401808060200182810382526021815260200180615dbb6021913960400191505060405180910390fd5b6000828152607a60209081526040918290208390558151838152915184927f047575f43f09a7a093d94ec483064acfc61b7e25c0de28017da442abf99cb91792908290030190a25050565b33611dfb818561348c565b5060008211611e51576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b611e5b818561111d565b821115611eaf576040805162461bcd60e51b815260206004820152601960248201527f6e6f7420656e6f75676820756e6c6f636b6564207374616b6500000000000000604482015290519081900360640190fd5b611eb98185613353565b611f0a576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152607160209081526040808320878452825280832086845290915290206002015415611f8b576040805162461bcd60e51b815260206004820152601360248201527f7772494420616c72656164792065786973747300000000000000000000000000604482015290519081900360640190fd5b611f9c81858460016000600161368e565b6001600160a01b038116600090815260716020908152604080832087845282528083208684529091529020600201829055611fd561240b565b6001600160a01b038216600090815260716020908152604080832088845282528083208784529091529020556120096140a4565b6001600160a01b038216600090815260716020908152604080832088845282528083208784529091528120600101919091556120469085906129bd565b8284826001600160a01b03167fd3bb4e423fbea695d16b982f9f682dc5f35152e5411646a8a5a79a6b02ba8d57856040518082815260200191505060405180910390a450505050565b61209833613109565b6120d35760405162461bcd60e51b8152600401808060200182810382526029815260200180615ce56029913960400191505060405180910390fd5b61211b898989898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915089905088886140a8565b606b5488111561130357606b889055505050505050505050565b6000818152606860209081526040808320600601546001600160a01b03168352607282528083208484529091529020545b919050565b606e5481565b600061217b615c05565b6121858484614285565b8051602082015160408301519293506121a7926110079163ffffffff612f3c16565b949350505050565b60006121bb8383612c12565b6121c7575060006111a0565b506001600160a01b03919091166000908152607360209081526040808320938352929052205490565b6121f8612553565b612249576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6089602052600090815260409020546001600160a01b031681565b6001600160a01b03821660009081526084602090815260408083208484529091528120905b8154811015612405576122fc6140a4565b82828154811061230857fe5b9060005260206000209060020201600101541080612343575081818154811061232d57fe5b9060005260206000209060020201600001546000145b156123fc57815482907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190811061237857fe5b906000526020600020906002020182828154811061239257fe5b60009182526020909120825460029092020190815560019182015491015581548290806123bb57fe5b60008281526020812060027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90930192830201818155600101559055612400565b6001015b6122eb565b50505050565b6067546001015b90565b60675481565b606a6020908152600091825260409182902080548351601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600186161502019093169290920491820184900484028101840190945280845290918301828280156124cc5780601f106124a1576101008083540402835291602001916124cc565b820191906000526020600020905b8154815290600101906020018083116124af57829003601f168201915b505050505081565b6082546001600160a01b031681565b606c5481565b6124f3828261348c565b611c8d576040805162461bcd60e51b815260206004820152601060248201527f6e6f7468696e6720746f20737461736800000000000000000000000000000000604482015290519081900360640190fd5b6033546001600160a01b031690565b6033546001600160a01b0316331490565b61256c612553565b6125bd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6125c6816142f3565b50565b607360209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b6125c6338234612f96565b6084602052826000526040600020602052816000526040600020818154811061262b57fe5b6000918252602090912060029091020180546001909101549093509150839050565b608160009054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b815260040160206040518083038186803b15801561269b57600080fd5b505afa1580156126af573d6000803e3d6000fd5b505050506040513d60208110156126c557600080fd5b505134101561271b576040805162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742073656c662d7374616b65000000000000000000604482015290519081900360640190fd5b60428114801561276657508181600081811061273357fe5b9050013560f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660c060f81b145b6127b7576040805162461bcd60e51b815260206004820152601060248201527f6d616c666f726d6564207075626b657900000000000000000000000000000000604482015290519081900360640190fd5b60866000838360405180838380828437604080519190930181900390208652506020850195909552505050016000205415612839576040805162461bcd60e51b815260206004820152600c60248201527f616c726561647920757365640000000000000000000000000000000000000000604482015290519081900360640190fd5b6128793383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061435d92505050565b611c8d33606b5434612f96565b607060209081526000928352604080842090915290825290205481565b606860205260009081526040902080546001820154600283015460038401546004850154600586015460069096015494959394929391929091906001600160a01b031687565b607460209081526000928352604080842090915290825290208054600182015460029092015490919083565b336129208185612c12565b612971576040805162461bcd60e51b815260206004820152600d60248201527f6e6f74206c6f636b656420757000000000000000000000000000000000000000604482015290519081900360640190fd5b612405818585856001614388565b600090815260686020526040902054608016151590565b607f546001600160a01b031681565b607a6020526000908152604090205481565b606b5481565b6129c6826148e5565b612a17576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f7220646f65736e2774206578697374000000000000000000604482015290519081900360640190fd5b60008281526068602052604090206003810154905415612a35575060005b606654604080517fa4066fbe000000000000000000000000000000000000000000000000000000008152600481018690526024810184905290516001600160a01b039092169163a4066fbe9160448082019260009290919082900301818387803b158015612aa257600080fd5b505af1158015612ab6573d6000803e3d6000fd5b50505050818015612ac657508015155b156116a8576066546000848152606a60205260409081902081517f242a6e3f0000000000000000000000000000000000000000000000000000000081526004810187815260248201938452825460027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001831615610100020190911604604483018190526001600160a01b039095169463242a6e3f94899493909160649091019084908015612bb75780601f10612b8c57610100808354040283529160200191612bb7565b820191906000526020600020905b815481529060010190602001808311612b9a57829003601f168201915b50509350505050600060405180830381600087803b158015612bd857600080fd5b505af1158015612bec573d6000803e3d6000fd5b50505050505050565b607260209081526000928352604080842090915290825290205481565b6001600160a01b038216600090815260736020908152604080832084845290915281206002015415801590612c6957506001600160a01b038316600090815260736020908152604080832085845290915290205415155b801561119d57506001600160a01b0383166000908152607360209081526040808320858452909152902060020154612c9f6140a4565b11159392505050565b607e5481565b3381612d01576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b612d0b8185612c12565b15612d5d576040805162461bcd60e51b815260206004820152601160248201527f616c7265616479206c6f636b6564207570000000000000000000000000000000604482015290519081900360640190fd5b612405818585856000614388565b6087546001600160a01b031681565b612d82612553565b612dd3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6125c6816148fc565b612de4615c05565b612dee8383613353565b612e3f576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b612e49838361348c565b50506001600160a01b0382166000908152606f6020908152604080832084845282528083208151606081018352815480825260018301549482018590526002909201549281018390529392612ea7926110079163ffffffff612f3c16565b905080612efb576040805162461bcd60e51b815260206004820152600c60248201527f7a65726f20726577617264730000000000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0384166000908152606f6020908152604080832086845290915281208181556001810182905560020155612f35816132b5565b5092915050565b60008282018381101561119d576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612f9f826148e5565b612ff0576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f7220646f65736e2774206578697374000000000000000000604482015290519081900360640190fd5b60008281526068602052604090205415613051576040805162461bcd60e51b815260206004820152601660248201527f76616c696461746f722069736e27742061637469766500000000000000000000604482015290519081900360640190fd5b61305e838383600161311d565b613067826149b5565b6116a85760405162461bcd60e51b8152600401808060200182810382526029815260200180615ddc6029913960400191505060405180910390fd5b6000806130ae83614a89565b90506001600160a01b0381166111a05782915050612166565b600061119d83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b1c565b6066546001600160a01b0390811691161490565b60008211613172576040805162461bcd60e51b815260206004820152600b60248201527f7a65726f20616d6f756e74000000000000000000000000000000000000000000604482015290519081900360640190fd5b61317c848461348c565b506001600160a01b03841660009081526072602090815260408083208684529091529020546131b1908363ffffffff612f3c16565b6001600160a01b03851660009081526072602090815260408083208784528252808320939093556068905220600301546131f1818463ffffffff612f3c16565b600085815260686020526040902060030155606c54613216908463ffffffff612f3c16565b606c5560008481526068602052604090205461324357606d5461323f908463ffffffff612f3c16565b606d555b61324e8482156129bd565b60408051848152905185916001600160a01b038816917f9a8f44850296624dadfd9c246d17e47171d35727a181bd090aa14bbbe00238bb9181900360200190a36000848152606860205260409020600601546118759086906001600160a01b0316846139de565b606654604080517f66e7ea0f0000000000000000000000000000000000000000000000000000000081523060048201526024810184905290516001600160a01b03909216916366e7ea0f9160448082019260009290919082900301818387803b15801561332157600080fd5b505af1158015613335573d6000803e3d6000fd5b505060765461334d925090508263ffffffff612f3c16565b60765550565b607b546000906001600160a01b031661336e575060016111a0565b607b54604080517f21d585c30000000000000000000000000000000000000000000000000000000081526001600160a01b03868116600483015260248201869052915191909216916321d585c3916044808301926020929190829003018186803b1580156133db57600080fd5b505afa1580156133ef573d6000803e3d6000fd5b505050506040513d602081101561340557600080fd5b50519392505050565b6000606061341a614bb8565b50905060005b81518110156134695781818151811061343557fe5b60200260200101516001600160a01b0316846001600160a01b0316141561346157600192505050612166565b600101613420565b5050506001600160a01b0390811660009081526089602052604090205416151590565b6000613496615c05565b6134a08484614ea3565b90506134ab83614fdb565b6001600160a01b0385166000818152607060209081526040808320888452825280832094909455918152606f8252828120868252825282902082516060810184528154815260018201549281019290925260020154918101919091526135119082615036565b6001600160a01b0385166000818152606f602090815260408083208884528252808320855181558583015160018083019190915595820151600291820155938352607482528083208884528252918290208251606081018452815481529481015491850191909152909101549082015261358b9082615036565b6001600160a01b0385166000908152607460209081526040808320878452825291829020835181559083015160018201559101516002909101556135cf8484612c12565b613632576001600160a01b0384166000818152607360209081526040808320878452825280832083815560018082018590556002808301869055600390920185905594845260748352818420888552909252822082815592830182905591909101555b61363c84846150a8565b602081015115158061364e5750805115155b806121a757506040015115159392505050565b600080613670868686866153bb565b905060006136808787878761545a565b919091019695505050505050565b6001600160a01b038616600090815260726020908152604080832088845282528083208054889003905560689091529020600301546136d3908563ffffffff6130c716565b600086815260686020526040902060030155606c546136f8908563ffffffff6130c716565b606c5560008581526068602052604090205461372557606d54613721908563ffffffff6130c716565b606d555b600061373086612135565b9050801580159061374d5750600086815260686020526040902054155b1561388257608160009054906101000a90046001600160a01b03166001600160a01b031663c5f530af6040518163ffffffff1660e01b815260040160206040518083038186803b1580156137a057600080fd5b505afa1580156137b4573d6000803e3d6000fd5b505050506040513d60208110156137ca57600080fd5b5051811015613831578215613826576040805162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742073656c662d7374616b65000000000000000000604482015290519081900360640190fd5b6138318660016138b4565b8115806138425750613842866149b5565b61387d5760405162461bcd60e51b8152600401808060200182810382526029815260200180615ddc6029913960400191505060405180910390fd5b61388d565b61388d8660016138b4565b600086815260686020526040902060060154612bec9088906001600160a01b0316866139de565b6000828152606860205260409020541580156138cf57508015155b156138fc57600082815260686020526040902060030154606d546138f89163ffffffff6130c716565b606d555b600082815260686020526040902054811115611c8d576000828152606860205260409020818155600201546139a45761393361240b565b60008381526068602052604090206002015561394d6140a4565b6000838152606860209081526040918290206001810184905560020154825190815290810192909252805184927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e4792908290030190a25b60408051828152905183917fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e919081900360200190a25050565b6082546001600160a01b0316156116a857608254604080516001600160a01b03868116602483015285811660448084019190915283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4a7702bb00000000000000000000000000000000000000000000000000000000178152925182516000959290921693627a120093928291908083835b60208310613ac157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101613a84565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038160008787f1925050503d8060008114613b24576040519150601f19603f3d011682016040523d82523d6000602084013e613b29565b606091505b505090508080613b37575081155b612405576040805162461bcd60e51b815260206004820152601b60248201527f676f7620766f746573207265636f756e74696e67206661696c65640000000000604482015290519081900360640190fd5b613b90615c05565b506001600160a01b038416600090815260716020908152604080832086845282528083208584528252918290208251606081018452815480825260018301549382019390935260029091015492810192909252613c34576040805162461bcd60e51b815260206004820152601560248201527f7265717565737420646f65736e27742065786973740000000000000000000000604482015290519081900360640190fd5b613c3e8585613353565b613c8f576040805162461bcd60e51b815260206004820152601860248201527f6f75747374616e64696e67207346544d2062616c616e63650000000000000000604482015290519081900360640190fd5b60208082015182516000878152606890935260409092206001015490919015801590613ccb575060008681526068602052604090206001015482115b15613cec575050600084815260686020526040902060018101546002909101545b608160009054906101000a90046001600160a01b03166001600160a01b031663b82b84276040518163ffffffff1660e01b815260040160206040518083038186803b158015613d3a57600080fd5b505afa158015613d4e573d6000803e3d6000fd5b505050506040513d6020811015613d6457600080fd5b50518201613d706140a4565b1015613dc3576040805162461bcd60e51b815260206004820152601660248201527f6e6f7420656e6f7567682074696d652070617373656400000000000000000000604482015290519081900360640190fd5b608160009054906101000a90046001600160a01b03166001600160a01b031663650acd666040518163ffffffff1660e01b815260040160206040518083038186803b158015613e1157600080fd5b505afa158015613e25573d6000803e3d6000fd5b505050506040513d6020811015613e3b57600080fd5b50518101613e4761240b565b1015613e9a576040805162461bcd60e51b815260206004820152601860248201527f6e6f7420656e6f7567682065706f636873207061737365640000000000000000604482015290519081900360640190fd5b6001600160a01b0387166000908152607160209081526040808320898452825280832088845290915281206002015490613ed38861297f565b90506000613ef58383607a60008d81526020019081526020016000205461553a565b6001600160a01b038b1660009081526071602090815260408083208d845282528083208c845290915281208181556001810182905560020155606e8054820190559050808311613f8c576040805162461bcd60e51b815260206004820152601660248201527f7374616b652069732066756c6c7920736c617368656400000000000000000000604482015290519081900360640190fd5b60006001600160a01b038816613fa8858463ffffffff6130c716565b604051600081818185875af1925050503d8060008114613fe4576040519150601f19603f3d011682016040523d82523d6000602084013e613fe9565b606091505b505090508061403f576040805162461bcd60e51b815260206004820152601260248201527f4661696c656420746f2073656e642046544d0000000000000000000000000000604482015290519081900360640190fd5b614048826142f3565b888a8c6001600160a01b03167f75e161b3e824b114fc1a33274bd7091918dd4e639cede50b78b15a4eea956a21876040518082815260200191505060405180910390a45050505050505050505050565b670de0b6b3a764000090565b4290565b6001600160a01b03881660009081526069602052604090205415614113576040805162461bcd60e51b815260206004820152601860248201527f76616c696461746f7220616c7265616479206578697374730000000000000000604482015290519081900360640190fd5b6001600160a01b03881660008181526069602090815260408083208b90558a8352606882528083208981556004810189905560058101889055600181018690556002810187905560060180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909417909355606a8152919020875161419c92890190615c26565b508551602080880191909120600090815260868252604090819020899055805186815291820185905280516001600160a01b038b16928a927f49bca1ed2666922f9f1690c26a569e1299c2a715fe57647d77e81adfabbf25bf92918290030190a3811561423e576040805183815260208101839052815189927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e47928290030190a25b841561427b5760408051868152905188917fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e919081900360200190a25b5050505050505050565b61428d615c05565b614295615c05565b61429f8484614ea3565b6001600160a01b0385166000908152606f6020908152604080832087845282529182902082516060810184528154815260018201549281019290925260020154918101919091529091506121a79082615036565b80156125c65760405160009082156108fc0290839083818181858288f19350505050158015614326573d6000803e3d6000fd5b506040805182815290517f8918bd6046d08b314e457977f29562c5d76a7030d79b1edba66e8a5da0b77ae89181900360200190a150565b606b8054600101908190556116a8838284600061437861240b565b6143806140a4565b6000806140a8565b6143918561340e565b156143e3576040805162461bcd60e51b815260206004820152600a60248201527f7265646972656374656400000000000000000000000000000000000000000000604482015290519081900360640190fd5b6143ed858561111d565b821115614441576040805162461bcd60e51b815260206004820152601060248201527f6e6f7420656e6f756768207374616b6500000000000000000000000000000000604482015290519081900360640190fd5b600084815260686020526040902054156144a2576040805162461bcd60e51b815260206004820152601660248201527f76616c696461746f722069736e27742061637469766500000000000000000000604482015290519081900360640190fd5b608160009054906101000a90046001600160a01b03166001600160a01b0316630d7b26096040518163ffffffff1660e01b815260040160206040518083038186803b1580156144f057600080fd5b505afa158015614504573d6000803e3d6000fd5b505050506040513d602081101561451a57600080fd5b505183108015906145a45750608160009054906101000a90046001600160a01b03166001600160a01b0316630d4955e36040518163ffffffff1660e01b815260040160206040518083038186803b15801561457457600080fd5b505afa158015614588573d6000803e3d6000fd5b505050506040513d602081101561459e57600080fd5b50518311155b6145f5576040805162461bcd60e51b815260206004820152601260248201527f696e636f7272656374206475726174696f6e0000000000000000000000000000604482015290519081900360640190fd5b6000614603846110076140a4565b6000868152606860205260409020600601549091506001600160a01b039081169087168114614696576001600160a01b038116600090815260736020908152604080832089845290915290206002015462278d00018211156146965760405162461bcd60e51b8152600401808060200182810382526025815260200180615d0e6025913960400191505060405180910390fd5b6146a0878761348c565b506146ab87876122c6565b6001600160a01b03871660009081526073602090815260408083208984529091529020831561480b576001600160a01b03881660009081526084602090815260408083208a84529091528120825490919061470a908b908b90806153bb565b905080156148085760408051808201909152818152600280850154602080840191825285546001818101885560008881529290922094519302909301918255519101558154601e10156147a4576040805162461bcd60e51b815260206004820152601860248201527f746f6f206d616e79206f6e676f696e672072656c6f636b730000000000000000604482015290519081900360640190fd5b8254606490048711806147b957508154600310155b806147cd5750826002015462127500018510155b6148085760405162461bcd60e51b8152600401808060200182810382526067815260200180615d546067913960800191505060405180910390fd5b50505b8060030154861015614864576040805162461bcd60e51b815260206004820152601f60248201527f6c6f636b7570206475726174696f6e2063616e6e6f7420646563726561736500604482015290519081900360640190fd5b8054614876908663ffffffff612f3c16565b815561488061240b565b600182015560028101839055600381018690556040805187815260208101879052815189926001600160a01b038c16927f138940e95abffcd789b497bf6188bba3afa5fbd22fb5c42c2f6018d1bf0f4e78929081900390910190a35050505050505050565b600090815260686020526040902060050154151590565b6001600160a01b0381166149415760405162461bcd60e51b8152600401808060200182810382526026815260200180615cbf6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000614a6e6149c2614098565b608154604080517f2265f2840000000000000000000000000000000000000000000000000000000081529051614a62926001600160a01b031691632265f284916004808301926020929190829003018186803b158015614a2157600080fd5b505afa158015614a35573d6000803e3d6000fd5b505050506040513d6020811015614a4b57600080fd5b5051614a5686612135565b9063ffffffff61559916565b9063ffffffff6155f216565b60008381526068602052604090206003015411159050919050565b6000606080614a96614bb8565b909250905060005b8251811015614afa57828181518110614ab357fe5b60200260200101516001600160a01b0316856001600160a01b03161415614af257818181518110614ae057fe5b60200260200101519350505050612166565b600101614a9e565b505050506001600160a01b039081166000908152608960205260409020541690565b60008184841115614bab5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614b70578181015183820152602001614b58565b50505050905090810190601f168015614b9d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50508183035b9392505050565b60408051600580825260c08201909252606091829182916020820160a080388339505060408051600580825260c0820190925292935060609291506020820160a0803883390190505090508051825114614c0e57fe5b7393419fcb5d9dc7989439f0512d4f737421ed48d982600081518110614c3057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507380f93310709624636852d0111fd6c4a6e02ed0aa81600081518110614c7257fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073fbcae1b28ca5039dafec4f10a89e022bc811839482600181518110614cb457fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507391b20102dfd2ff1b00d0915266584009d0b1ae3981600181518110614cf657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250507315c2ec517905fb3282f26f3ac3e12889755a2ed782600281518110614d3857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073ca3c54c11172a7263300a801e9937780b5143c0881600281518110614d7a57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073bdaaec5f9317cc63d26fd7d79ad17372ccd7d76382600381518110614dbc57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050735a1cad027eace4c052f5dee0f42da6c62e39b77981600381518110614dfe57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073f72148504819a1d1b038694b02d299f65bfa312d82600481518110614e4057fe5b60200260200101906001600160a01b031690816001600160a01b031681525050734a15b527475977d9b0cb3fcfe825d6aa7428fafc81600481518110614e8257fe5b6001600160a01b039092166020928302919091019091015290925090509091565b614eab615c05565b6001600160a01b038316600090815260706020908152604080832085845290915281205490614ed984614fdb565b90506000614ee78686615634565b905081811115614ef45750805b82811015614eff5750815b6001600160a01b03861660008181526073602090815260408083208984528252808320938352607282528083208984529091528120548254909190614f4b90839063ffffffff6130c716565b90506000614f5f84600001548a8988615711565b9050614f69615c05565b614f7782866003015461577f565b9050614f85838b8a89615711565b9150614f8f615c05565b614f9a83600061577f565b9050614fa8858c898b615711565b9250614fb2615c05565b614fbd84600061577f565b9050614fca838383615940565b9d9c50505050505050505050505050565b6000818152606860205260408120600201541561502e5760008281526068602052604090206002015460675410156150165750606754612166565b50600081815260686020526040902060020154612166565b505060675490565b61503e615c05565b604080516060810190915282518451829161505f919063ffffffff612f3c16565b815260200161507f84602001518660200151612f3c90919063ffffffff16565b815260200161509f84604001518660400151612f3c90919063ffffffff16565b90529392505050565b6001600160a01b0382166000908152607460209081526040808320848452909152902060018101548154600290910401806150e4575050611c8d565b6001600160a01b0384166000908152607360209081526040808320868452909152812060038101548154919290919061511c8361595b565b90508061512e57505050505050611c8d565b600061514784614a62637cbe4cbf614a568c89886159e1565b6001600160a01b038a1660009081526072602090815260408083208c845290915281205491925061522b615179614098565b614a6261520d608160009054906101000a90046001600160a01b03166001600160a01b031663a77865156040518163ffffffff1660e01b815260040160206040518083038186803b1580156151cd57600080fd5b505afa1580156151e1573d6000803e3d6000fd5b505050506040513d60208110156151f757600080fd5b5051615201614098565b9063ffffffff6130c716565b614a56670de0b6b3a7640000614a628c838a8c63ffffffff61559916565b60008b8152606860205260409020600601549091506001600160a01b038c81169116141561532657600061526a600a614a62600b614a568f8c8b615a92565b9050615320615277614098565b608154604080517fa77865150000000000000000000000000000000000000000000000000000000081529051614a62926001600160a01b03169163a7786515916004808301926020929190829003018186803b1580156152d657600080fd5b505afa1580156152ea573d6000803e3d6000fd5b505050506040513d602081101561530057600080fd5b5051614a56670de0b6b3a7640000614a628d83898d63ffffffff61559916565b82019150505b61533a82614a62838863ffffffff61559916565b9050615344615c05565b61534e828861577f565b905060008160000151600283602001518161536557fe5b04019050808a11156153ac578a54615389908b90614a62908463ffffffff61559916565b8b5560018b01546153a6908b90614a62908463ffffffff61559916565b60018c01555b50505050505050505050505050565b6001600160a01b03841660009081526074602090815260408083208684529091528120805482906153f8908590614a62908863ffffffff61559916565b9050600061541785614a6288866001015461559990919063ffffffff16565b83549091506002820483019061542d90846130c7565b84556001840154615444908363ffffffff6130c716565b6001909401939093555090915050949350505050565b600061546685856122c6565b6001600160a01b0385166000908152608460209081526040808320878452909152812090805b825481101561552f5760006154c886614a62898786815481106154ab57fe5b60009182526020909120600290910201549063ffffffff61559916565b90506154f7818584815481106154da57fe5b60009182526020909120600290910201549063ffffffff6130c716565b84838154811061550357fe5b6000918252602090912060029091020155615524838263ffffffff612f3c16565b92505060010161548c565b509695505050505050565b6000821580615550575061554c614098565b8210155b1561555d57506000614bb1565b615588600161100761556d614098565b614a6286615579614098565b8a91900363ffffffff61559916565b905083811115614bb1575082614bb1565b6000826155a8575060006111a0565b828202828482816155b557fe5b041461119d5760405162461bcd60e51b8152600401808060200182810382526021815260200180615d336021913960400191505060405180910390fd5b600061119d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250615b2a565b6001600160a01b0382166000908152607360209081526040808320848452909152812060010154606754615669858583615b85565b156156775791506111a09050565b615682858584615b85565b615691576000925050506111a0565b808211156156a4576000925050506111a0565b808210156156d7576002818301046156bd868683615b85565b156156cd578060010192506156d1565b8091505b506156a4565b806156e7576000925050506111a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01949350505050565b6000818310615722575060006121a7565b600083815260776020818152604080842088855260019081018352818520548786529383528185208986520190915290912054615774615760614098565b614a6289614a56858763ffffffff6130c716565b979650505050505050565b615787615c05565b60405180606001604052806000815260200160008152602001600081525090506000608160009054906101000a90046001600160a01b03166001600160a01b0316635e2308d26040518163ffffffff1660e01b815260040160206040518083038186803b1580156157f757600080fd5b505afa15801561580b573d6000803e3d6000fd5b505050506040513d602081101561582157600080fd5b50519050821561591957600081615836614098565b03905060006158c8608160009054906101000a90046001600160a01b03166001600160a01b0316630d4955e36040518163ffffffff1660e01b815260040160206040518083038186803b15801561588c57600080fd5b505afa1580156158a0573d6000803e3d6000fd5b505050506040513d60208110156158b657600080fd5b5051614a62848863ffffffff61559916565b905060006158e96158d7614098565b614a628987860163ffffffff61559916565b90506159066158f6614098565b614a62898763ffffffff61559916565b602086018190529003845250612f359050565b615934615924614098565b614a62868463ffffffff61559916565b60408301525092915050565b615948615c05565b6121a76159558585615036565b83615036565b60008060056067548161596a57fe5b04905061271081111561597c57506127105b60675481900360009081526077602052604090206007015480158061599f575081155b156159af57600092505050612166565b6000826159be836152016140a4565b816159c557fe5b04905080600f0260010185816159d757fe5b0495945050505050565b6000806159f0846152016140a4565b9050600080805b601e8111615a745760675481870290036000818152607760205260409020600781015486811015615a415760028411615a395789975050505050505050614bb1565b505050615a74565b60008b81526002830160205260409020548015615a645795508585615a64578095505b5050600190920191506159f79050565b50818103600560048802048111156157745786945050505050614bb1565b600083815260686020526040812060030154600182615ab3866152016140a4565b905060015b601e8111615b1457606754818702900360008181526077602052604090206007810154841115615ae9575050615b14565b60008a8152602082905260409020548015615b0957958601956001909501945b505050600101615ab8565b50818381615b1e57fe5b04979650505050505050565b60008183615b795760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b70578181015183820152602001614b58565b5060008385816159d757fe5b6001600160a01b038316600090815260736020908152604080832085845290915281206001015482108015906121a757506001600160a01b0384166000908152607360209081526040808320868452909152902060020154615be683615bf0565b1115949350505050565b60009081526077602052604090206007015490565b60405180606001604052806000815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c6757805160ff1916838001178555615c94565b82800160010185558215615c94579182015b82811115615c94578251825591602001919060010190615c79565b50615ca0929150615ca4565b5090565b61241291905b80821115615ca05760008155600101615caa56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737363616c6c6572206973206e6f7420746865204e6f64654472697665724175746820636f6e747261637476616c696461746f722773206c6f636b75702077696c6c20656e6420746f6f206561726c79536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746f6f206672657175656e742072656c6f636b7320286769746875622e636f6d2f46616e746f6d2d666f756e646174696f6e2f6f706572612d7366632f77696b692f4c6f636b75702d63616c6c732d7265666572656e63652372652d6c6f636b2d7374616b65296d757374206265206c657373207468616e206f7220657175616c20746f20312e3076616c696461746f7227732064656c65676174696f6e73206c696d69742069732065786365656465646c6f636b6564207374616b652069732067726561746572207468616e207468652077686f6c65207374616b65a265627a7a72315820355bb02dc9bdc4f689b18b8f31f5621f2a48f106f86eca94e61db7659872453664736f6c63430005110032
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.