FTM Price: $0.43 (-0.94%)
Gas: 21 Gwei

Contract

0xFC00FACE00000000000000000000000000000000
 

Overview

FTM Balance

Fantom LogoFantom LogoFantom Logo1,423,612,753.143225102273131131 FTM

FTM Value

$609,161,341.58 (@ $0.43/FTM)

Token Holdings

More Info

Private Name Tags

ContractCreator:

GENESIS at txn GENESIS_0

Sponsored

Transaction Hash
Method
Block
From
To
Value
Restake Rewards760172642024-02-20 23:09:296 mins ago1708470569IN
Fantom: SFC
0 FTM0.0074740434.5743835
Restake Rewards760168182024-02-20 23:01:1515 mins ago1708470075IN
Fantom: SFC
0 FTM0.0066811925.08002058
Delegate760162252024-02-20 22:49:4226 mins ago1708469382IN
Fantom: SFC
25 FTM0.0048382721.75728416
Claim Rewards760160542024-02-20 22:46:2129 mins ago1708469181IN
Fantom: SFC
0 FTM0.0040999120.79265158
Claim Rewards760160222024-02-20 22:45:4930 mins ago1708469149IN
Fantom: SFC
0 FTM0.0040999120.79265158
Claim Rewards760159882024-02-20 22:45:1431 mins ago1708469114IN
Fantom: SFC
0 FTM0.0040999120.79265158
Withdraw760159522024-02-20 22:44:3831 mins ago1708469078IN
Fantom: SFC
0 FTM0.0016683923.9980611
Claim Rewards760159302024-02-20 22:44:1732 mins ago1708469057IN
Fantom: SFC
0 FTM0.0040999120.79265158
Claim Rewards760158992024-02-20 22:43:4532 mins ago1708469025IN
Fantom: SFC
0 FTM0.0040999120.79265158
Claim Rewards760158652024-02-20 22:43:0633 mins ago1708468986IN
Fantom: SFC
0 FTM0.0036777919.87395389
Claim Rewards760155692024-02-20 22:38:2037 mins ago1708468700IN
Fantom: SFC
0 FTM0.0046109623.61290623
Restake Rewards760152612024-02-20 22:32:3643 mins ago1708468356IN
Fantom: SFC
0 FTM0.0045974122.14222505
Restake Rewards760152472024-02-20 22:32:1744 mins ago1708468337IN
Fantom: SFC
0 FTM0.0045974122.14222505
Restake Rewards760152282024-02-20 22:31:5644 mins ago1708468316IN
Fantom: SFC
0 FTM0.0044964621.65602503
Restake Rewards760151992024-02-20 22:31:2644 mins ago1708468286IN
Fantom: SFC
0 FTM0.004862418.25261643
Delegate760147482024-02-20 22:22:3253 mins ago1708467752IN
Fantom: SFC
8 FTM0.0036723716.73161923
Claim Rewards760147312024-02-20 22:22:0354 mins ago1708467723IN
Fantom: SFC
0 FTM0.0029739716.07067411
Claim Rewards760147242024-02-20 22:21:5454 mins ago1708467714IN
Fantom: SFC
0 FTM0.0027537916.07067411
Restake Rewards760129432024-02-20 21:46:311 hr 29 mins ago1708465591IN
Fantom: SFC
0 FTM0.0037476418.04955719
Withdraw760128302024-02-20 21:42:331 hr 33 mins ago1708465353IN
Fantom: SFC
0 FTM0.0012873718.47708386
Restake Rewards760126482024-02-20 21:34:431 hr 41 mins ago1708464883IN
Fantom: SFC
0 FTM0.0055233720.71823499
Claim Rewards760126432024-02-20 21:34:391 hr 41 mins ago1708464879IN
Fantom: SFC
0 FTM0.0052437220.17568913
Restake Rewards760126322024-02-20 21:34:071 hr 42 mins ago1708464847IN
Fantom: SFC
0 FTM0.0048801920.17568913
Restake Rewards760121322024-02-20 21:13:592 hrs 2 mins ago1708463639IN
Fantom: SFC
0 FTM0.0053036719.89412721
Lock Stake760119902024-02-20 21:09:482 hrs 6 mins ago1708463388IN
Fantom: SFC
0 FTM0.0045845419.67673888
View all transactions

Latest 25 internal transactions (View All)

Parent Txn Hash Block From To Value
760176602024-02-20 23:16:0810 secs ago1708470968
Fantom: SFC
2.28618331 FTM
760174372024-02-20 23:12:174 mins ago1708470737
Fantom: SFC
3.76599008 FTM
760171992024-02-20 23:08:227 mins ago1708470502
Fantom: SFC
2.12071235 FTM
760169692024-02-20 23:03:5212 mins ago1708470232
Fantom: SFC
2.90366009 FTM
760167502024-02-20 22:59:5716 mins ago1708469997
Fantom: SFC
3.86259864 FTM
760165702024-02-20 22:56:1020 mins ago1708469770
Fantom: SFC
2.10203856 FTM
760163452024-02-20 22:52:0224 mins ago1708469522
Fantom: SFC
2.6120375 FTM
760161512024-02-20 22:47:5528 mins ago1708469275
Fantom: SFC
1.4942979 FTM
760158972024-02-20 22:43:3732 mins ago1708469017
Fantom: SFC
1.945573 FTM
760156672024-02-20 22:39:5836 mins ago1708468798
Fantom: SFC
1.86011716 FTM
760154282024-02-20 22:35:3940 mins ago1708468539
Fantom: SFC
1.46940636 FTM
760151972024-02-20 22:31:1944 mins ago1708468279
Fantom: SFC
1.74335859 FTM
760149612024-02-20 22:26:3749 mins ago1708467997
Fantom: SFC
1.49016702 FTM
760147382024-02-20 22:22:1354 mins ago1708467733
Fantom: SFC
3.34265867 FTM
760145142024-02-20 22:17:4458 mins ago1708467464
Fantom: SFC
1.82665606 FTM
760143092024-02-20 22:13:051 hr 3 mins ago1708467185
Fantom: SFC
1.47641478 FTM
760141242024-02-20 22:09:061 hr 7 mins ago1708466946
Fantom: SFC
1.4373986 FTM
760138822024-02-20 22:04:181 hr 12 mins ago1708466658
Fantom: SFC
3.24995119 FTM
760134702024-02-20 21:56:421 hr 19 mins ago1708466202
Fantom: SFC
2.70109037 FTM
760129242024-02-20 21:45:501 hr 30 mins ago1708465550
Fantom: SFC
4.31553516 FTM
760126782024-02-20 21:35:511 hr 40 mins ago1708464951
Fantom: SFC
4.36705746 FTM
760124882024-02-20 21:27:251 hr 48 mins ago1708464445
Fantom: SFC
3.84026814 FTM
760123572024-02-20 21:21:231 hr 54 mins ago1708464083
Fantom: SFC
3.18677262 FTM
760120402024-02-20 21:10:592 hrs 5 mins ago1708463459
Fantom: SFC
3.24304808 FTM
760117402024-02-20 21:00:482 hrs 15 mins ago1708462848
Fantom: SFC
4.04034039 FTM
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SFC

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
Yes with 10000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at ftmscan.com on 2022-04-05
*/

// File: contracts/sfc/SFCI.sol

pragma solidity ^0.5.0;

interface SFCI {
    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 mintFTM(address receiver, uint256 amount, string calldata justification) 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(address v) external view returns (address);
}

// File: contracts/common/Initializable.sol

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;
}

// File: contracts/ownership/Ownable.sol

pragma solidity ^0.5.0;


/**
 * @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;
}

// File: @openzeppelin/contracts/math/SafeMath.sol

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;
    }
}

// File: contracts/sfc/NodeDriver.sol

pragma solidity ^0.5.0;






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;
}

// File: contracts/version/Version.sol

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.4
        return "304";
    }
}

// File: contracts/common/Decimal.sol

pragma solidity ^0.5.0;

library Decimal {
    // unit is used for decimals, e.g. 0.123456
    function unit() internal pure returns (uint256) {
        return 1e18;
    }
}

// File: contracts/sfc/ConstantsManager.sol

pragma solidity ^0.5.0;




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;
    }
}

// File: contracts/sfc/SFCState.sol

pragma solidity ^0.5.0;




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;
}

// File: contracts/sfc/SFCBase.sol

pragma solidity ^0.5.0;


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;
    }
}

// File: contracts/sfc/GasPriceConstants.sol

pragma solidity ^0.5.0;


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;
    }
}

// File: contracts/sfc/SFC.sol

pragma solidity ^0.5.0;




/**
 * @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);
    }

    event UpdatedBaseRewardPerSec(uint256 value);
    event UpdatedOfflinePenaltyThreshold(uint256 blocksNum, uint256 period);

    /*
    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;
    }

    /*
    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)("");
        }
    }


    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);
    }
}

Contract Security Audit

Contract ABI

[{"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":"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":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"UpdatedBaseRewardPerSec","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"blocksNum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"period","type":"uint256"}],"name":"UpdatedOfflinePenaltyThreshold","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"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":true,"inputs":[],"name":"constsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","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":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"},{"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":"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":false,"inputs":[{"internalType":"uint256","name":"sealedEpoch","type":"uint256"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"address","name":"nodeDriver","type":"address"},{"internalType":"address","name":"lib","type":"address"},{"internalType":"address","name":"_c","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","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":[],"name":"lastValidatorID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"offlineTime","type":"uint256[]"},{"internalType":"uint256[]","name":"offlineBlocks","type":"uint256[]"},{"internalType":"uint256[]","name":"uptimes","type":"uint256[]"},{"internalType":"uint256[]","name":"originatedTxsFee","type":"uint256[]"},{"internalType":"uint256","name":"epochGas","type":"uint256"}],"name":"sealEpoch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"nextValidatorIDs","type":"uint256[]"}],"name":"sealEpochValidators","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":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":"address","name":"v","type":"address"}],"name":"updateConstsAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"updateLibAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"updateStakeTokenizerAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"updateTreasuryAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"v","type":"address"}],"name":"updateVoteBookAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"internalType":"bytes3","name":"","type":"bytes3"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"voteBookAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]

6080604052600436106102855760003560e01c80638b0e9f3f11610153578063c65ee0e1116100cb578063d46fa5181161007f578063e08d7e6611610064578063e08d7e6614610b1f578063e6f45adf14610b9c578063f2fde38b14610bcf57610285565b8063d46fa51814610af5578063d96ed50514610b0a57610285565b8063cc8343aa116100b0578063cc8343aa14610a51578063cfd4766314610a83578063cfdbb7cd14610abc57610285565b8063c65ee0e114610a12578063c7be95de14610a3c57610285565b8063a2f6e6bc11610122578063b5d8962711610107578063b5d8962714610959578063b810e411146109c4578063c5f956af146109fd57610285565b8063a2f6e6bc146108ed578063a86a056f1461092057610285565b80638b0e9f3f1461083b5780638da5cb5b146108505780638f32d59b1461086557806396c7ee461461088e57610285565b8063592fe0c0116102015780637cacb1d6116101b5578063854873e11161019a578063854873e114610754578063860c2750146107f3578063893675c61461082657610285565b80637cacb1d61461070c578063841e45611461072157610285565b8063670322f8116101e6578063670322f8146106a9578063715018a6146106e257806376671808146106f757610285565b8063592fe0c0146105215780635fab23a81461069457610285565b80631f2701521161025857806339b80c001161023d57806339b80c001461044257806354fd4d50146104a4578063550359a0146104ee57610285565b80631f270152146103d057806328f731481461042d57610285565b80630135b1db146102ee5780630e559d821461033357806310e51e141461036457806318160ddd146103bb575b366102d7576040805162461bcd60e51b815260206004820152601560248201527f7472616e7366657273206e6f7420616c6c6f7765640000000000000000000000604482015290519081900360640190fd5b6080546102ec906001600160a01b0316610c02565b005b3480156102fa57600080fd5b506103216004803603602081101561031157600080fd5b50356001600160a01b0316610c2b565b60408051918252519081900360200190f35b34801561033f57600080fd5b50610348610c3d565b604080516001600160a01b039092168252519081900360200190f35b34801561037057600080fd5b506102ec600480360360c081101561038757600080fd5b508035906020810135906001600160a01b0360408201358116916060810135821691608082013581169160a0013516610c4c565b3480156103c757600080fd5b50610321610dd9565b3480156103dc57600080fd5b5061040f600480360360608110156103f357600080fd5b506001600160a01b038135169060208101359060400135610ddf565b60408051938452602084019290925282820152519081900360600190f35b34801561043957600080fd5b50610321610e11565b34801561044e57600080fd5b5061046c6004803603602081101561046557600080fd5b5035610e17565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b3480156104b057600080fd5b506104b9610e59565b604080517fffffff00000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b3480156104fa57600080fd5b506102ec6004803603602081101561051157600080fd5b50356001600160a01b0316610e7e565b34801561052d57600080fd5b506102ec600480360360a081101561054457600080fd5b81019060208101813564010000000081111561055f57600080fd5b82018360208201111561057157600080fd5b8035906020019184602083028401116401000000008311171561059357600080fd5b9193909290916020810190356401000000008111156105b157600080fd5b8201836020820111156105c357600080fd5b803590602001918460208302840111640100000000831117156105e557600080fd5b91939092909160208101903564010000000081111561060357600080fd5b82018360208201111561061557600080fd5b8035906020019184602083028401116401000000008311171561063757600080fd5b91939092909160208101903564010000000081111561065557600080fd5b82018360208201111561066757600080fd5b8035906020019184602083028401116401000000008311171561068957600080fd5b919350915035610f11565b3480156106a057600080fd5b506103216111cc565b3480156106b557600080fd5b50610321600480360360408110156106cc57600080fd5b506001600160a01b0381351690602001356111d2565b3480156106ee57600080fd5b506102ec611216565b34801561070357600080fd5b506103216112d1565b34801561071857600080fd5b506103216112da565b34801561072d57600080fd5b506102ec6004803603602081101561074457600080fd5b50356001600160a01b03166112e0565b34801561076057600080fd5b5061077e6004803603602081101561077757600080fd5b5035611373565b6040805160208082528351818301528351919283929083019185019080838360005b838110156107b85781810151838201526020016107a0565b50505050905090810190601f1680156107e55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156107ff57600080fd5b506102ec6004803603602081101561081657600080fd5b50356001600160a01b031661142c565b34801561083257600080fd5b506103486114bf565b34801561084757600080fd5b506103216114ce565b34801561085c57600080fd5b506103486114d4565b34801561087157600080fd5b5061087a6114e3565b604080519115158252519081900360200190f35b34801561089a57600080fd5b506108c7600480360360408110156108b157600080fd5b506001600160a01b0381351690602001356114f4565b604080519485526020850193909352838301919091526060830152519081900360800190f35b3480156108f957600080fd5b506102ec6004803603602081101561091057600080fd5b50356001600160a01b0316611526565b34801561092c57600080fd5b506103216004803603604081101561094357600080fd5b506001600160a01b0381351690602001356115b9565b34801561096557600080fd5b506109836004803603602081101561097c57600080fd5b50356115d6565b604080519788526020880196909652868601949094526060860192909252608085015260a08401526001600160a01b031660c0830152519081900360e00190f35b3480156109d057600080fd5b5061040f600480360360408110156109e757600080fd5b506001600160a01b03813516906020013561161c565b348015610a0957600080fd5b50610348611648565b348015610a1e57600080fd5b5061032160048036036020811015610a3557600080fd5b5035611657565b348015610a4857600080fd5b50610321611669565b348015610a5d57600080fd5b506102ec60048036036040811015610a7457600080fd5b5080359060200135151561166f565b348015610a8f57600080fd5b5061032160048036036040811015610aa657600080fd5b506001600160a01b03813516906020013561189e565b348015610ac857600080fd5b5061087a60048036036040811015610adf57600080fd5b506001600160a01b0381351690602001356118bb565b348015610b0157600080fd5b50610348611952565b348015610b1657600080fd5b50610321611961565b348015610b2b57600080fd5b506102ec60048036036020811015610b4257600080fd5b810190602081018135640100000000811115610b5d57600080fd5b820183602082011115610b6f57600080fd5b80359060200191846020830284011164010000000083111715610b9157600080fd5b509092509050611967565b348015610ba857600080fd5b506102ec60048036036020811015610bbf57600080fd5b50356001600160a01b0316611aab565b348015610bdb57600080fd5b506102ec60048036036020811015610bf257600080fd5b50356001600160a01b0316611b3e565b3660008037600080366000845af43d6000803e808015610c21573d6000f35b3d6000fd5b505050565b60696020526000908152604090205481565b607b546001600160a01b031681565b600054610100900460ff1680610c655750610c65611ba3565b80610c73575060005460ff16155b610cae5760405162461bcd60e51b815260040180806020018281038252602e81526020018061335a602e913960400191505060405180910390fd5b600054610100900460ff16158015610d1457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b610d1d82611ba9565b6067879055606680546001600160a01b038088167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556080805487841690831617905560818054928616929091169190911790556076869055610d84611d0b565b607e55610d8f611d14565b6000888152607760205260409020600701558015610dd057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50505050505050565b60765481565b607160209081526000938452604080852082529284528284209052825290208054600182015460029092015490919083565b606d5481565b607760205280600052604060002060009150905080600701549080600801549080600901549080600a01549080600b01549080600c01549080600d0154905087565b7f33303400000000000000000000000000000000000000000000000000000000005b90565b610e866114e3565b610ed7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b608280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610f1a33611d18565b610f555760405162461bcd60e51b81526004018080602001828103825260298152602001806133106029913960400191505060405180910390fd5b600060776000610f636112d1565b81526020019081526020016000209050606081600601805480602002602001604051908101604052809291908181526020018280548015610fc357602002820191906000526020600020905b815481526020019060010190808311610faf575b5050505050905061104a82828d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d2f92505050565b6067546000908152607760205260409020600781015460019061106b611d14565b111561108257816007015461107e611d14565b0390505b611104818584868d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611f3692505050565b61110e8186612720565b50506111186112d1565b606755611123611d14565b6007830155608154604080517fd9a7c1f900000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169163d9a7c1f991600480820192602092909190829003018186803b15801561118657600080fd5b505afa15801561119a573d6000803e3d6000fd5b505050506040513d60208110156111b057600080fd5b5051600b83015550607654600d90910155505050505050505050565b606e5481565b60006111de83836118bb565b6111ea57506000611210565b506001600160a01b03821660009081526073602090815260408083208484529091529020545b92915050565b61121e6114e3565b61126f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60675460010190565b60675481565b6112e86114e3565b611339576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b607f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b606a6020908152600091825260409182902080548351601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600186161502019093169290920491820184900484028101840190945280845290918301828280156114245780601f106113f957610100808354040283529160200191611424565b820191906000526020600020905b81548152906001019060200180831161140757829003601f168201915b505050505081565b6114346114e3565b611485576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b608180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6082546001600160a01b031681565b606c5481565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b607360209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b61152e6114e3565b61157f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b607b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b607060209081526000928352604080842090915290825290205481565b606860205260009081526040902080546001820154600283015460038401546004850154600586015460069096015494959394929391929091906001600160a01b031687565b607460209081526000928352604080842090915290825290208054600182015460029092015490919083565b607f546001600160a01b031681565b607a6020526000908152604090205481565b606b5481565b61167882612899565b6116c9576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f7220646f65736e2774206578697374000000000000000000604482015290519081900360640190fd5b600082815260686020526040902060038101549054156116e7575060005b606654604080517fa4066fbe000000000000000000000000000000000000000000000000000000008152600481018690526024810184905290516001600160a01b039092169163a4066fbe9160448082019260009290919082900301818387803b15801561175457600080fd5b505af1158015611768573d6000803e3d6000fd5b5050505081801561177857508015155b15610c26576066546000848152606a60205260409081902081517f242a6e3f0000000000000000000000000000000000000000000000000000000081526004810187815260248201938452825460027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001831615610100020190911604604483018190526001600160a01b039095169463242a6e3f948994939091606490910190849080156118695780601f1061183e57610100808354040283529160200191611869565b820191906000526020600020905b81548152906001019060200180831161184c57829003601f168201915b50509350505050600060405180830381600087803b15801561188a57600080fd5b505af1158015610dd0573d6000803e3d6000fd5b607260209081526000928352604080842090915290825290205481565b6001600160a01b03821660009081526073602090815260408083208484529091528120600201541580159061191257506001600160a01b038316600090815260736020908152604080832085845290915290205415155b801561194b57506001600160a01b0383166000908152607360209081526040808320858452909152902060020154611948611d14565b11155b9392505050565b6081546001600160a01b031690565b607e5481565b61197033611d18565b6119ab5760405162461bcd60e51b81526004018080602001828103825260298152602001806133106029913960400191505060405180910390fd5b6000607760006119b96112d1565b8152602001908152602001600020905060008090505b82811015611a325760008484838181106119e557fe5b60209081029290920135600081815260688452604080822060030154948890529020839055600c860154909350611a2391508263ffffffff6128b016565b600c85015550506001016119cf565b50611a41600682018484613238565b50606654607e54604080517f07aaf3440000000000000000000000000000000000000000000000000000000081526004810192909252516001600160a01b03909216916307aaf3449160248082019260009290919082900301818387803b15801561188a57600080fd5b611ab36114e3565b611b04576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b608080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611b466114e3565b611b97576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611ba08161290a565b50565b303b1590565b600054610100900460ff1680611bc25750611bc2611ba3565b80611bd0575060005460ff16155b611c0b5760405162461bcd60e51b815260040180806020018281038252602e81526020018061335a602e913960400191505060405180910390fd5b600054610100900460ff16158015611c7157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015611d0757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050565b64174876e80090565b4290565b6066546001600160a01b038281169116145b919050565b60005b8351811015611f2f57608160009054906101000a90046001600160a01b03166001600160a01b0316635a68f01a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d8957600080fd5b505afa158015611d9d573d6000803e3d6000fd5b505050506040513d6020811015611db357600080fd5b50518251839083908110611dc357fe5b6020026020010151118015611e655750608160009054906101000a90046001600160a01b03166001600160a01b031662cc7f836040518163ffffffff1660e01b815260040160206040518083038186803b158015611e2057600080fd5b505afa158015611e34573d6000803e3d6000fd5b505050506040513d6020811015611e4a57600080fd5b50518351849083908110611e5a57fe5b602002602001015110155b15611ea657611e88848281518110611e7957fe5b602002602001015160086129c3565b611ea6848281518110611e9757fe5b6020026020010151600061166f565b828181518110611eb257fe5b6020026020010151856004016000868481518110611ecc57fe5b6020026020010151815260200190815260200160002081905550818181518110611ef257fe5b6020026020010151856005016000868481518110611f0c57fe5b602090810291909101810151825281019190915260400160002055600101611d32565b5050505050565b611f3e61327f565b6040518060a001604052808551604051908082528060200260200182016040528015611f74578160200160208202803883390190505b508152602001600081526020018551604051908082528060200260200182016040528015611fac578160200160208202803883390190505b508152602001600081526020016000815250905060008090505b84518110156120c7576000866003016000878481518110611fe357fe5b6020026020010151815260200190815260200160002054905060008090508185848151811061200e57fe5b60200260200101511115612035578185848151811061202957fe5b60200260200101510390505b8986848151811061204257fe5b602002602001015182028161205357fe5b048460400151848151811061206457fe5b60200260200101818152505061209e8460400151848151811061208357fe5b602002602001015185606001516128b090919063ffffffff16565b606085015260808401516120b8908263ffffffff6128b016565b60808501525050600101611fc6565b5060005b845181101561219057878482815181106120e157fe5b6020026020010151898684815181106120f657fe5b60200260200101518a60000160008a878151811061211057fe5b6020026020010151815260200190815260200160002054028161212f57fe5b04028161213857fe5b048260000151828151811061214957fe5b6020026020010181815250506121838260000151828151811061216857fe5b602002602001015183602001516128b090919063ffffffff16565b60208301526001016120cb565b5060005b84518110156125cf57600061223d89608160009054906101000a90046001600160a01b03166001600160a01b031663d9a7c1f96040518163ffffffff1660e01b815260040160206040518083038186803b1580156121f157600080fd5b505afa158015612205573d6000803e3d6000fd5b505050506040513d602081101561221b57600080fd5b5051855180518690811061222b57fe5b60200260200101518660200151612aed565b905061227961226c84608001518560400151858151811061225a57fe5b60200260200101518660600151612b3c565b829063ffffffff6128b016565b9050600086838151811061228957fe5b60209081029190910181015160008181526068835260408082206006015460815482517fa778651500000000000000000000000000000000000000000000000000000000815292519496506001600160a01b0391821695939461233f948994929093169263a77865159260048082019391829003018186803b15801561230e57600080fd5b505afa158015612322573d6000803e3d6000fd5b505050506040513d602081101561233857600080fd5b5051612ca5565b6001600160a01b038316600090815260726020908152604080832087845290915290205490915080156124e65760008161237985876111d2565b84028161238257fe5b0490508083036123906132ae565b6001600160a01b03861660009081526073602090815260408083208a84529091529020600301546123c2908490612cc2565b90506123cc6132ae565b6123d7836000612cc2565b6001600160a01b0388166000908152606f602090815260408083208c8452825291829020825160608101845281548152600182015492810192909252600201549181019190915290915061242c908383612e84565b6001600160a01b0388166000818152606f602090815260408083208d84528252808320855181558583015160018083019190915595820151600291820155938352607482528083208d8452825291829020825160608101845281548152948101549185019190915290910154908201526124a7908383612e84565b6001600160a01b03881660009081526074602090815260408083208c845282529182902083518155908301516001820155910151600290910155505050505b600084815260686020526040812060030154838703918115612518578161250b612e9f565b84028161251457fe5b0490505b808e600101600089815260200190815260200160002054018f6001016000898152602001908152602001600020819055508a898151811061255557fe5b60200260200101518f6003016000898152602001908152602001600020819055508b898151811061258257fe5b60200260200101518e600201600089815260200190815260200160002054018f60020160008981526020019081526020016000208190555050505050505050508080600101915050612194565b50608081015160088701819055602082015160098801556060820151600a880155607654111561260d57600886015460768054919091039055612613565b60006076555b607f546001600160a01b031615610dd057600061262e612e9f565b608160009054906101000a90046001600160a01b03166001600160a01b03166394c3e9146040518163ffffffff1660e01b815260040160206040518083038186803b15801561267c57600080fd5b505afa158015612690573d6000803e3d6000fd5b505050506040513d60208110156126a657600080fd5b5051608084015102816126b557fe5b0490506126c181612eab565b607f546040516001600160a01b03909116908290600081818185875af1925050503d806000811461270e576040519150601f19603f3d011682016040523d82523d6000602084013e612713565b606091505b5050505050505050505050565b608154604080517f3a3ef66c00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691633a3ef66c916004808301926020929190829003018186803b15801561277e57600080fd5b505afa158015612792573d6000803e3d6000fd5b505050506040513d60208110156127a857600080fd5b5051830260010190506000816127bc612e9f565b8402816127c557fe5b0490506000608160009054906101000a90046001600160a01b03166001600160a01b0316632c8c36a56040518163ffffffff1660e01b815260040160206040518083038186803b15801561281857600080fd5b505afa15801561282c573d6000803e3d6000fd5b505050506040513d602081101561284257600080fd5b50519050848101612851612e9f565b8202838702018161285e57fe5b04915061286a82612f49565b91506000612876612e9f565b83607e54028161288257fe5b04905061288e81612fb7565b607e55505050505050565b600090815260686020526040902060050154151590565b60008282018381101561194b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03811661294f5760405162461bcd60e51b81526004018080602001828103825260268152602001806132ea6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000828152606860205260409020541580156129de57508015155b15612a0b57600082815260686020526040902060030154606d54612a079163ffffffff612fed16565b606d555b600082815260686020526040902054811115611d0757600082815260686020526040902081815560020154612ab357612a426112d1565b600083815260686020526040902060020155612a5c611d14565b6000838152606860209081526040918290206001810184905560020154825190815290810192909252805184927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e4792908290030190a25b60408051828152905183917fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e919081900360200190a25050565b600082612afc57506000612b34565b6000612b0e868663ffffffff61302f16565b9050612b3083612b24838763ffffffff61302f16565b9063ffffffff61308816565b9150505b949350505050565b600082612b4b5750600061194b565b6000612b6183612b24878763ffffffff61302f16565b9050612c9c612b6e612e9f565b608154604080517f94c3e9140000000000000000000000000000000000000000000000000000000081529051612b24926001600160a01b0316916394c3e914916004808301926020929190829003018186803b158015612bcd57600080fd5b505afa158015612be1573d6000803e3d6000fd5b505050506040513d6020811015612bf757600080fd5b5051608154604080517fc74dd62100000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169163c74dd62191600480820192602092909190829003018186803b158015612c5757600080fd5b505afa158015612c6b573d6000803e3d6000fd5b505050506040513d6020811015612c8157600080fd5b5051612c8b612e9f565b03038461302f90919063ffffffff16565b95945050505050565b600061194b612cb2612e9f565b612b24858563ffffffff61302f16565b612cca6132ae565b60405180606001604052806000815260200160008152602001600081525090506000608160009054906101000a90046001600160a01b03166001600160a01b0316635e2308d26040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3a57600080fd5b505afa158015612d4e573d6000803e3d6000fd5b505050506040513d6020811015612d6457600080fd5b505190508215612e5c57600081612d79612e9f565b0390506000612e0b608160009054906101000a90046001600160a01b03166001600160a01b0316630d4955e36040518163ffffffff1660e01b815260040160206040518083038186803b158015612dcf57600080fd5b505afa158015612de3573d6000803e3d6000fd5b505050506040513d6020811015612df957600080fd5b5051612b24848863ffffffff61302f16565b90506000612e2c612e1a612e9f565b612b248987860163ffffffff61302f16565b9050612e49612e39612e9f565b612b24898763ffffffff61302f16565b602086018190529003845250612e7d9050565b612e77612e67612e9f565b612b24868463ffffffff61302f16565b60408301525b5092915050565b612e8c6132ae565b612b34612e9985856130ca565b836130ca565b670de0b6b3a764000090565b606654604080517f66e7ea0f0000000000000000000000000000000000000000000000000000000081523060048201526024810184905290516001600160a01b03909216916366e7ea0f9160448082019260009290919082900301818387803b158015612f1757600080fd5b505af1158015612f2b573d6000803e3d6000fd5b5050607654612f43925090508263ffffffff6128b016565b60765550565b60006064612f55612e9f565b60690281612f5f57fe5b04821115612f83576064612f71612e9f565b60690281612f7b57fe5b049050611d2a565b6064612f8d612e9f565b605f0281612f9757fe5b04821015612fb3576064612fa9612e9f565b605f0281612f7b57fe5b5090565b600066038d7ea4c68000821115612fd6575066038d7ea4c68000611d2a565b633b9aca00821015612fb35750633b9aca00611d2a565b600061194b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061313c565b60008261303e57506000611210565b8282028284828161304b57fe5b041461194b5760405162461bcd60e51b81526004018080602001828103825260218152602001806133396021913960400191505060405180910390fd5b600061194b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506131d3565b6130d26132ae565b60408051606081019091528251845182916130f3919063ffffffff6128b016565b8152602001613113846020015186602001516128b090919063ffffffff16565b8152602001613133846040015186604001516128b090919063ffffffff16565b90529392505050565b600081848411156131cb5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613190578181015183820152602001613178565b50505050905090810190601f1680156131bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836132225760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613190578181015183820152602001613178565b50600083858161322e57fe5b0495945050505050565b828054828255906000526020600020908101928215613273579160200282015b82811115613273578235825591602001919060010190613258565b50612fb39291506132cf565b6040518060a0016040528060608152602001600081526020016060815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b610e7b91905b80821115612fb357600081556001016132d556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737363616c6c6572206973206e6f7420746865204e6f64654472697665724175746820636f6e7472616374536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7231582090349e52e0caa583e7da14dc7da02b7e29e446e7e6228363cd89f70b48534ada64736f6c63430005110032

Deployed Bytecode

0x6080604052600436106102855760003560e01c80638b0e9f3f11610153578063c65ee0e1116100cb578063d46fa5181161007f578063e08d7e6611610064578063e08d7e6614610b1f578063e6f45adf14610b9c578063f2fde38b14610bcf57610285565b8063d46fa51814610af5578063d96ed50514610b0a57610285565b8063cc8343aa116100b0578063cc8343aa14610a51578063cfd4766314610a83578063cfdbb7cd14610abc57610285565b8063c65ee0e114610a12578063c7be95de14610a3c57610285565b8063a2f6e6bc11610122578063b5d8962711610107578063b5d8962714610959578063b810e411146109c4578063c5f956af146109fd57610285565b8063a2f6e6bc146108ed578063a86a056f1461092057610285565b80638b0e9f3f1461083b5780638da5cb5b146108505780638f32d59b1461086557806396c7ee461461088e57610285565b8063592fe0c0116102015780637cacb1d6116101b5578063854873e11161019a578063854873e114610754578063860c2750146107f3578063893675c61461082657610285565b80637cacb1d61461070c578063841e45611461072157610285565b8063670322f8116101e6578063670322f8146106a9578063715018a6146106e257806376671808146106f757610285565b8063592fe0c0146105215780635fab23a81461069457610285565b80631f2701521161025857806339b80c001161023d57806339b80c001461044257806354fd4d50146104a4578063550359a0146104ee57610285565b80631f270152146103d057806328f731481461042d57610285565b80630135b1db146102ee5780630e559d821461033357806310e51e141461036457806318160ddd146103bb575b366102d7576040805162461bcd60e51b815260206004820152601560248201527f7472616e7366657273206e6f7420616c6c6f7765640000000000000000000000604482015290519081900360640190fd5b6080546102ec906001600160a01b0316610c02565b005b3480156102fa57600080fd5b506103216004803603602081101561031157600080fd5b50356001600160a01b0316610c2b565b60408051918252519081900360200190f35b34801561033f57600080fd5b50610348610c3d565b604080516001600160a01b039092168252519081900360200190f35b34801561037057600080fd5b506102ec600480360360c081101561038757600080fd5b508035906020810135906001600160a01b0360408201358116916060810135821691608082013581169160a0013516610c4c565b3480156103c757600080fd5b50610321610dd9565b3480156103dc57600080fd5b5061040f600480360360608110156103f357600080fd5b506001600160a01b038135169060208101359060400135610ddf565b60408051938452602084019290925282820152519081900360600190f35b34801561043957600080fd5b50610321610e11565b34801561044e57600080fd5b5061046c6004803603602081101561046557600080fd5b5035610e17565b604080519788526020880196909652868601949094526060860192909252608085015260a084015260c0830152519081900360e00190f35b3480156104b057600080fd5b506104b9610e59565b604080517fffffff00000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b3480156104fa57600080fd5b506102ec6004803603602081101561051157600080fd5b50356001600160a01b0316610e7e565b34801561052d57600080fd5b506102ec600480360360a081101561054457600080fd5b81019060208101813564010000000081111561055f57600080fd5b82018360208201111561057157600080fd5b8035906020019184602083028401116401000000008311171561059357600080fd5b9193909290916020810190356401000000008111156105b157600080fd5b8201836020820111156105c357600080fd5b803590602001918460208302840111640100000000831117156105e557600080fd5b91939092909160208101903564010000000081111561060357600080fd5b82018360208201111561061557600080fd5b8035906020019184602083028401116401000000008311171561063757600080fd5b91939092909160208101903564010000000081111561065557600080fd5b82018360208201111561066757600080fd5b8035906020019184602083028401116401000000008311171561068957600080fd5b919350915035610f11565b3480156106a057600080fd5b506103216111cc565b3480156106b557600080fd5b50610321600480360360408110156106cc57600080fd5b506001600160a01b0381351690602001356111d2565b3480156106ee57600080fd5b506102ec611216565b34801561070357600080fd5b506103216112d1565b34801561071857600080fd5b506103216112da565b34801561072d57600080fd5b506102ec6004803603602081101561074457600080fd5b50356001600160a01b03166112e0565b34801561076057600080fd5b5061077e6004803603602081101561077757600080fd5b5035611373565b6040805160208082528351818301528351919283929083019185019080838360005b838110156107b85781810151838201526020016107a0565b50505050905090810190601f1680156107e55780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156107ff57600080fd5b506102ec6004803603602081101561081657600080fd5b50356001600160a01b031661142c565b34801561083257600080fd5b506103486114bf565b34801561084757600080fd5b506103216114ce565b34801561085c57600080fd5b506103486114d4565b34801561087157600080fd5b5061087a6114e3565b604080519115158252519081900360200190f35b34801561089a57600080fd5b506108c7600480360360408110156108b157600080fd5b506001600160a01b0381351690602001356114f4565b604080519485526020850193909352838301919091526060830152519081900360800190f35b3480156108f957600080fd5b506102ec6004803603602081101561091057600080fd5b50356001600160a01b0316611526565b34801561092c57600080fd5b506103216004803603604081101561094357600080fd5b506001600160a01b0381351690602001356115b9565b34801561096557600080fd5b506109836004803603602081101561097c57600080fd5b50356115d6565b604080519788526020880196909652868601949094526060860192909252608085015260a08401526001600160a01b031660c0830152519081900360e00190f35b3480156109d057600080fd5b5061040f600480360360408110156109e757600080fd5b506001600160a01b03813516906020013561161c565b348015610a0957600080fd5b50610348611648565b348015610a1e57600080fd5b5061032160048036036020811015610a3557600080fd5b5035611657565b348015610a4857600080fd5b50610321611669565b348015610a5d57600080fd5b506102ec60048036036040811015610a7457600080fd5b5080359060200135151561166f565b348015610a8f57600080fd5b5061032160048036036040811015610aa657600080fd5b506001600160a01b03813516906020013561189e565b348015610ac857600080fd5b5061087a60048036036040811015610adf57600080fd5b506001600160a01b0381351690602001356118bb565b348015610b0157600080fd5b50610348611952565b348015610b1657600080fd5b50610321611961565b348015610b2b57600080fd5b506102ec60048036036020811015610b4257600080fd5b810190602081018135640100000000811115610b5d57600080fd5b820183602082011115610b6f57600080fd5b80359060200191846020830284011164010000000083111715610b9157600080fd5b509092509050611967565b348015610ba857600080fd5b506102ec60048036036020811015610bbf57600080fd5b50356001600160a01b0316611aab565b348015610bdb57600080fd5b506102ec60048036036020811015610bf257600080fd5b50356001600160a01b0316611b3e565b3660008037600080366000845af43d6000803e808015610c21573d6000f35b3d6000fd5b505050565b60696020526000908152604090205481565b607b546001600160a01b031681565b600054610100900460ff1680610c655750610c65611ba3565b80610c73575060005460ff16155b610cae5760405162461bcd60e51b815260040180806020018281038252602e81526020018061335a602e913960400191505060405180910390fd5b600054610100900460ff16158015610d1457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b610d1d82611ba9565b6067879055606680546001600160a01b038088167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556080805487841690831617905560818054928616929091169190911790556076869055610d84611d0b565b607e55610d8f611d14565b6000888152607760205260409020600701558015610dd057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b50505050505050565b60765481565b607160209081526000938452604080852082529284528284209052825290208054600182015460029092015490919083565b606d5481565b607760205280600052604060002060009150905080600701549080600801549080600901549080600a01549080600b01549080600c01549080600d0154905087565b7f33303400000000000000000000000000000000000000000000000000000000005b90565b610e866114e3565b610ed7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b608280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610f1a33611d18565b610f555760405162461bcd60e51b81526004018080602001828103825260298152602001806133106029913960400191505060405180910390fd5b600060776000610f636112d1565b81526020019081526020016000209050606081600601805480602002602001604051908101604052809291908181526020018280548015610fc357602002820191906000526020600020905b815481526020019060010190808311610faf575b5050505050905061104a82828d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d2f92505050565b6067546000908152607760205260409020600781015460019061106b611d14565b111561108257816007015461107e611d14565b0390505b611104818584868d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611f3692505050565b61110e8186612720565b50506111186112d1565b606755611123611d14565b6007830155608154604080517fd9a7c1f900000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169163d9a7c1f991600480820192602092909190829003018186803b15801561118657600080fd5b505afa15801561119a573d6000803e3d6000fd5b505050506040513d60208110156111b057600080fd5b5051600b83015550607654600d90910155505050505050505050565b606e5481565b60006111de83836118bb565b6111ea57506000611210565b506001600160a01b03821660009081526073602090815260408083208484529091529020545b92915050565b61121e6114e3565b61126f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60675460010190565b60675481565b6112e86114e3565b611339576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b607f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b606a6020908152600091825260409182902080548351601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600186161502019093169290920491820184900484028101840190945280845290918301828280156114245780601f106113f957610100808354040283529160200191611424565b820191906000526020600020905b81548152906001019060200180831161140757829003601f168201915b505050505081565b6114346114e3565b611485576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b608180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6082546001600160a01b031681565b606c5481565b6033546001600160a01b031690565b6033546001600160a01b0316331490565b607360209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b61152e6114e3565b61157f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b607b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b607060209081526000928352604080842090915290825290205481565b606860205260009081526040902080546001820154600283015460038401546004850154600586015460069096015494959394929391929091906001600160a01b031687565b607460209081526000928352604080842090915290825290208054600182015460029092015490919083565b607f546001600160a01b031681565b607a6020526000908152604090205481565b606b5481565b61167882612899565b6116c9576040805162461bcd60e51b815260206004820152601760248201527f76616c696461746f7220646f65736e2774206578697374000000000000000000604482015290519081900360640190fd5b600082815260686020526040902060038101549054156116e7575060005b606654604080517fa4066fbe000000000000000000000000000000000000000000000000000000008152600481018690526024810184905290516001600160a01b039092169163a4066fbe9160448082019260009290919082900301818387803b15801561175457600080fd5b505af1158015611768573d6000803e3d6000fd5b5050505081801561177857508015155b15610c26576066546000848152606a60205260409081902081517f242a6e3f0000000000000000000000000000000000000000000000000000000081526004810187815260248201938452825460027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001831615610100020190911604604483018190526001600160a01b039095169463242a6e3f948994939091606490910190849080156118695780601f1061183e57610100808354040283529160200191611869565b820191906000526020600020905b81548152906001019060200180831161184c57829003601f168201915b50509350505050600060405180830381600087803b15801561188a57600080fd5b505af1158015610dd0573d6000803e3d6000fd5b607260209081526000928352604080842090915290825290205481565b6001600160a01b03821660009081526073602090815260408083208484529091528120600201541580159061191257506001600160a01b038316600090815260736020908152604080832085845290915290205415155b801561194b57506001600160a01b0383166000908152607360209081526040808320858452909152902060020154611948611d14565b11155b9392505050565b6081546001600160a01b031690565b607e5481565b61197033611d18565b6119ab5760405162461bcd60e51b81526004018080602001828103825260298152602001806133106029913960400191505060405180910390fd5b6000607760006119b96112d1565b8152602001908152602001600020905060008090505b82811015611a325760008484838181106119e557fe5b60209081029290920135600081815260688452604080822060030154948890529020839055600c860154909350611a2391508263ffffffff6128b016565b600c85015550506001016119cf565b50611a41600682018484613238565b50606654607e54604080517f07aaf3440000000000000000000000000000000000000000000000000000000081526004810192909252516001600160a01b03909216916307aaf3449160248082019260009290919082900301818387803b15801561188a57600080fd5b611ab36114e3565b611b04576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b608080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b611b466114e3565b611b97576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b611ba08161290a565b50565b303b1590565b600054610100900460ff1680611bc25750611bc2611ba3565b80611bd0575060005460ff16155b611c0b5760405162461bcd60e51b815260040180806020018281038252602e81526020018061335a602e913960400191505060405180910390fd5b600054610100900460ff16158015611c7157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015611d0757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050565b64174876e80090565b4290565b6066546001600160a01b038281169116145b919050565b60005b8351811015611f2f57608160009054906101000a90046001600160a01b03166001600160a01b0316635a68f01a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d8957600080fd5b505afa158015611d9d573d6000803e3d6000fd5b505050506040513d6020811015611db357600080fd5b50518251839083908110611dc357fe5b6020026020010151118015611e655750608160009054906101000a90046001600160a01b03166001600160a01b031662cc7f836040518163ffffffff1660e01b815260040160206040518083038186803b158015611e2057600080fd5b505afa158015611e34573d6000803e3d6000fd5b505050506040513d6020811015611e4a57600080fd5b50518351849083908110611e5a57fe5b602002602001015110155b15611ea657611e88848281518110611e7957fe5b602002602001015160086129c3565b611ea6848281518110611e9757fe5b6020026020010151600061166f565b828181518110611eb257fe5b6020026020010151856004016000868481518110611ecc57fe5b6020026020010151815260200190815260200160002081905550818181518110611ef257fe5b6020026020010151856005016000868481518110611f0c57fe5b602090810291909101810151825281019190915260400160002055600101611d32565b5050505050565b611f3e61327f565b6040518060a001604052808551604051908082528060200260200182016040528015611f74578160200160208202803883390190505b508152602001600081526020018551604051908082528060200260200182016040528015611fac578160200160208202803883390190505b508152602001600081526020016000815250905060008090505b84518110156120c7576000866003016000878481518110611fe357fe5b6020026020010151815260200190815260200160002054905060008090508185848151811061200e57fe5b60200260200101511115612035578185848151811061202957fe5b60200260200101510390505b8986848151811061204257fe5b602002602001015182028161205357fe5b048460400151848151811061206457fe5b60200260200101818152505061209e8460400151848151811061208357fe5b602002602001015185606001516128b090919063ffffffff16565b606085015260808401516120b8908263ffffffff6128b016565b60808501525050600101611fc6565b5060005b845181101561219057878482815181106120e157fe5b6020026020010151898684815181106120f657fe5b60200260200101518a60000160008a878151811061211057fe5b6020026020010151815260200190815260200160002054028161212f57fe5b04028161213857fe5b048260000151828151811061214957fe5b6020026020010181815250506121838260000151828151811061216857fe5b602002602001015183602001516128b090919063ffffffff16565b60208301526001016120cb565b5060005b84518110156125cf57600061223d89608160009054906101000a90046001600160a01b03166001600160a01b031663d9a7c1f96040518163ffffffff1660e01b815260040160206040518083038186803b1580156121f157600080fd5b505afa158015612205573d6000803e3d6000fd5b505050506040513d602081101561221b57600080fd5b5051855180518690811061222b57fe5b60200260200101518660200151612aed565b905061227961226c84608001518560400151858151811061225a57fe5b60200260200101518660600151612b3c565b829063ffffffff6128b016565b9050600086838151811061228957fe5b60209081029190910181015160008181526068835260408082206006015460815482517fa778651500000000000000000000000000000000000000000000000000000000815292519496506001600160a01b0391821695939461233f948994929093169263a77865159260048082019391829003018186803b15801561230e57600080fd5b505afa158015612322573d6000803e3d6000fd5b505050506040513d602081101561233857600080fd5b5051612ca5565b6001600160a01b038316600090815260726020908152604080832087845290915290205490915080156124e65760008161237985876111d2565b84028161238257fe5b0490508083036123906132ae565b6001600160a01b03861660009081526073602090815260408083208a84529091529020600301546123c2908490612cc2565b90506123cc6132ae565b6123d7836000612cc2565b6001600160a01b0388166000908152606f602090815260408083208c8452825291829020825160608101845281548152600182015492810192909252600201549181019190915290915061242c908383612e84565b6001600160a01b0388166000818152606f602090815260408083208d84528252808320855181558583015160018083019190915595820151600291820155938352607482528083208d8452825291829020825160608101845281548152948101549185019190915290910154908201526124a7908383612e84565b6001600160a01b03881660009081526074602090815260408083208c845282529182902083518155908301516001820155910151600290910155505050505b600084815260686020526040812060030154838703918115612518578161250b612e9f565b84028161251457fe5b0490505b808e600101600089815260200190815260200160002054018f6001016000898152602001908152602001600020819055508a898151811061255557fe5b60200260200101518f6003016000898152602001908152602001600020819055508b898151811061258257fe5b60200260200101518e600201600089815260200190815260200160002054018f60020160008981526020019081526020016000208190555050505050505050508080600101915050612194565b50608081015160088701819055602082015160098801556060820151600a880155607654111561260d57600886015460768054919091039055612613565b60006076555b607f546001600160a01b031615610dd057600061262e612e9f565b608160009054906101000a90046001600160a01b03166001600160a01b03166394c3e9146040518163ffffffff1660e01b815260040160206040518083038186803b15801561267c57600080fd5b505afa158015612690573d6000803e3d6000fd5b505050506040513d60208110156126a657600080fd5b5051608084015102816126b557fe5b0490506126c181612eab565b607f546040516001600160a01b03909116908290600081818185875af1925050503d806000811461270e576040519150601f19603f3d011682016040523d82523d6000602084013e612713565b606091505b5050505050505050505050565b608154604080517f3a3ef66c00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691633a3ef66c916004808301926020929190829003018186803b15801561277e57600080fd5b505afa158015612792573d6000803e3d6000fd5b505050506040513d60208110156127a857600080fd5b5051830260010190506000816127bc612e9f565b8402816127c557fe5b0490506000608160009054906101000a90046001600160a01b03166001600160a01b0316632c8c36a56040518163ffffffff1660e01b815260040160206040518083038186803b15801561281857600080fd5b505afa15801561282c573d6000803e3d6000fd5b505050506040513d602081101561284257600080fd5b50519050848101612851612e9f565b8202838702018161285e57fe5b04915061286a82612f49565b91506000612876612e9f565b83607e54028161288257fe5b04905061288e81612fb7565b607e55505050505050565b600090815260686020526040902060050154151590565b60008282018381101561194b576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03811661294f5760405162461bcd60e51b81526004018080602001828103825260268152602001806132ea6026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6000828152606860205260409020541580156129de57508015155b15612a0b57600082815260686020526040902060030154606d54612a079163ffffffff612fed16565b606d555b600082815260686020526040902054811115611d0757600082815260686020526040902081815560020154612ab357612a426112d1565b600083815260686020526040902060020155612a5c611d14565b6000838152606860209081526040918290206001810184905560020154825190815290810192909252805184927fac4801c32a6067ff757446524ee4e7a373797278ac3c883eac5c693b4ad72e4792908290030190a25b60408051828152905183917fcd35267e7654194727477d6c78b541a553483cff7f92a055d17868d3da6e953e919081900360200190a25050565b600082612afc57506000612b34565b6000612b0e868663ffffffff61302f16565b9050612b3083612b24838763ffffffff61302f16565b9063ffffffff61308816565b9150505b949350505050565b600082612b4b5750600061194b565b6000612b6183612b24878763ffffffff61302f16565b9050612c9c612b6e612e9f565b608154604080517f94c3e9140000000000000000000000000000000000000000000000000000000081529051612b24926001600160a01b0316916394c3e914916004808301926020929190829003018186803b158015612bcd57600080fd5b505afa158015612be1573d6000803e3d6000fd5b505050506040513d6020811015612bf757600080fd5b5051608154604080517fc74dd62100000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169163c74dd62191600480820192602092909190829003018186803b158015612c5757600080fd5b505afa158015612c6b573d6000803e3d6000fd5b505050506040513d6020811015612c8157600080fd5b5051612c8b612e9f565b03038461302f90919063ffffffff16565b95945050505050565b600061194b612cb2612e9f565b612b24858563ffffffff61302f16565b612cca6132ae565b60405180606001604052806000815260200160008152602001600081525090506000608160009054906101000a90046001600160a01b03166001600160a01b0316635e2308d26040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3a57600080fd5b505afa158015612d4e573d6000803e3d6000fd5b505050506040513d6020811015612d6457600080fd5b505190508215612e5c57600081612d79612e9f565b0390506000612e0b608160009054906101000a90046001600160a01b03166001600160a01b0316630d4955e36040518163ffffffff1660e01b815260040160206040518083038186803b158015612dcf57600080fd5b505afa158015612de3573d6000803e3d6000fd5b505050506040513d6020811015612df957600080fd5b5051612b24848863ffffffff61302f16565b90506000612e2c612e1a612e9f565b612b248987860163ffffffff61302f16565b9050612e49612e39612e9f565b612b24898763ffffffff61302f16565b602086018190529003845250612e7d9050565b612e77612e67612e9f565b612b24868463ffffffff61302f16565b60408301525b5092915050565b612e8c6132ae565b612b34612e9985856130ca565b836130ca565b670de0b6b3a764000090565b606654604080517f66e7ea0f0000000000000000000000000000000000000000000000000000000081523060048201526024810184905290516001600160a01b03909216916366e7ea0f9160448082019260009290919082900301818387803b158015612f1757600080fd5b505af1158015612f2b573d6000803e3d6000fd5b5050607654612f43925090508263ffffffff6128b016565b60765550565b60006064612f55612e9f565b60690281612f5f57fe5b04821115612f83576064612f71612e9f565b60690281612f7b57fe5b049050611d2a565b6064612f8d612e9f565b605f0281612f9757fe5b04821015612fb3576064612fa9612e9f565b605f0281612f7b57fe5b5090565b600066038d7ea4c68000821115612fd6575066038d7ea4c68000611d2a565b633b9aca00821015612fb35750633b9aca00611d2a565b600061194b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061313c565b60008261303e57506000611210565b8282028284828161304b57fe5b041461194b5760405162461bcd60e51b81526004018080602001828103825260218152602001806133396021913960400191505060405180910390fd5b600061194b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506131d3565b6130d26132ae565b60408051606081019091528251845182916130f3919063ffffffff6128b016565b8152602001613113846020015186602001516128b090919063ffffffff16565b8152602001613133846040015186604001516128b090919063ffffffff16565b90529392505050565b600081848411156131cb5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613190578181015183820152602001613178565b50505050905090810190601f1680156131bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836132225760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613190578181015183820152602001613178565b50600083858161322e57fe5b0495945050505050565b828054828255906000526020600020908101928215613273579160200282015b82811115613273578235825591602001919060010190613258565b50612fb39291506132cf565b6040518060a0016040528060608152602001600081526020016060815260200160008152602001600081525090565b60405180606001604052806000815260200160008152602001600081525090565b610e7b91905b80821115612fb357600081556001016132d556fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737363616c6c6572206973206e6f7420746865204e6f64654472697665724175746820636f6e7472616374536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a7231582090349e52e0caa583e7da14dc7da02b7e29e446e7e6228363cd89f70b48534ada64736f6c63430005110032

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.