FTM Testnet

Contract

0x9F266aDa47711C2A942A4987A0B5dd5344887aEa

Overview

FTM Balance

Fantom LogoFantom LogoFantom Logo0 FTM

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Create122132322022-11-23 10:36:28748 days ago1669199788IN
0x9F266aDa...344887aEa
100 FTM0.006180952.5
Create121800112022-11-21 13:07:07750 days ago1669036027IN
0x9F266aDa...344887aEa
100 FTM0.006182192.5
Create121799882022-11-21 13:04:39750 days ago1669035879IN
0x9F266aDa...344887aEa
100 FTM0.006073372.5
Create121799772022-11-21 13:03:11750 days ago1669035791IN
0x9F266aDa...344887aEa
100 FTM0.006226532.5
Create121798922022-11-21 12:52:24750 days ago1669035144IN
0x9F266aDa...344887aEa
100 FTM0.006182632.5
Create121798752022-11-21 12:50:12750 days ago1669035012IN
0x9F266aDa...344887aEa
100 FTM0.006115712.5
Create121797562022-11-21 12:39:50750 days ago1669034390IN
0x9F266aDa...344887aEa
100 FTM0.006071532.5
Create121797342022-11-21 12:37:30750 days ago1669034250IN
0x9F266aDa...344887aEa
100 FTM0.006114222.5
Create121796182022-11-21 12:26:58750 days ago1669033618IN
0x9F266aDa...344887aEa
100 FTM0.006080462.5
Create121795902022-11-21 12:24:06750 days ago1669033446IN
0x9F266aDa...344887aEa
100 FTM0.006288922.5
Create121794832022-11-21 12:13:43750 days ago1669032823IN
0x9F266aDa...344887aEa
100 FTM0.006070222.5
Create121794752022-11-21 12:12:23750 days ago1669032743IN
0x9F266aDa...344887aEa
100 FTM0.006070142.5
Create121794452022-11-21 12:10:39750 days ago1669032639IN
0x9F266aDa...344887aEa
100 FTM0.006223852.5
Create121780122022-11-21 10:27:16750 days ago1669026436IN
0x9F266aDa...344887aEa
100 FTM0.006338492.5
Create121778392022-11-21 10:16:48750 days ago1669025808IN
0x9F266aDa...344887aEa
100 FTM0.006229982.5
Create121765442022-11-21 9:00:12750 days ago1669021212IN
0x9F266aDa...344887aEa
100 FTM0.00622792.5
Create121354732022-11-18 7:26:51753 days ago1668756411IN
0x9F266aDa...344887aEa
100 FTM0.006292932.5
Create121354012022-11-18 7:21:46753 days ago1668756106IN
0x9F266aDa...344887aEa
100 FTM0.006398052.5

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
122132322022-11-23 10:36:28748 days ago1669199788
0x9F266aDa...344887aEa
100 FTM
122132322022-11-23 10:36:28748 days ago1669199788
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121800112022-11-21 13:07:07750 days ago1669036027
0x9F266aDa...344887aEa
100 FTM
121800112022-11-21 13:07:07750 days ago1669036027
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121799882022-11-21 13:04:39750 days ago1669035879
0x9F266aDa...344887aEa
100 FTM
121799882022-11-21 13:04:39750 days ago1669035879
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121799772022-11-21 13:03:11750 days ago1669035791
0x9F266aDa...344887aEa
100 FTM
121799772022-11-21 13:03:11750 days ago1669035791
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121798922022-11-21 12:52:24750 days ago1669035144
0x9F266aDa...344887aEa
100 FTM
121798922022-11-21 12:52:24750 days ago1669035144
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121798752022-11-21 12:50:12750 days ago1669035012
0x9F266aDa...344887aEa
100 FTM
121798752022-11-21 12:50:12750 days ago1669035012
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121797562022-11-21 12:39:50750 days ago1669034390
0x9F266aDa...344887aEa
100 FTM
121797562022-11-21 12:39:50750 days ago1669034390
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121797342022-11-21 12:37:30750 days ago1669034250
0x9F266aDa...344887aEa
100 FTM
121797342022-11-21 12:37:30750 days ago1669034250
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121796182022-11-21 12:26:58750 days ago1669033618
0x9F266aDa...344887aEa
100 FTM
121796182022-11-21 12:26:58750 days ago1669033618
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121795902022-11-21 12:24:06750 days ago1669033446
0x9F266aDa...344887aEa
100 FTM
121795902022-11-21 12:24:06750 days ago1669033446
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121794832022-11-21 12:13:43750 days ago1669032823
0x9F266aDa...344887aEa
100 FTM
121794832022-11-21 12:13:43750 days ago1669032823
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121794752022-11-21 12:12:23750 days ago1669032743
0x9F266aDa...344887aEa
100 FTM
121794752022-11-21 12:12:23750 days ago1669032743
0x9F266aDa...344887aEa
 Contract Creation100 FTM
121794452022-11-21 12:10:39750 days ago1669032639
0x9F266aDa...344887aEa
100 FTM
View All Internal Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x09F44D7F...09A51d7C3
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
NetworkParameterProposalFactory

Compiler Version
v0.5.17+commit.d19bba13

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 22 : NetworkParameterProposalFactory.sol
pragma solidity ^0.5.0;

import "../common/SafeMath.sol";
import "../governance/Governance.sol";
import "../proposal/NetworkParameterProposal.sol";
import "../verifiers/ScopedVerifier.sol";

contract NetworkParameterProposalFactory is ScopedVerifier {
    using SafeMath for uint256;
    Governance internal gov;
    address internal constsAddress;
    address public lastNetworkProposal;

    constructor(address _governance, address _constsAddress) public {
        gov = Governance(_governance);
        constsAddress = _constsAddress;
    }

    function create(
        string memory __description,
        uint8 __methodID,
        uint256[] memory __optionVals,
        uint256 __minVotes, uint256 __minAgreement, uint256 __start, uint256 __minEnd, uint256 __maxEnd
    ) public payable {
        NetworkParameterProposal proposal = new NetworkParameterProposal(
            __description,
            __methodID,
            __optionVals,
            constsAddress,
            __minVotes,
            __minAgreement,
            __start,
            __minEnd,
            __maxEnd,
            address(0));
        proposal.transferOwnership(msg.sender);
        lastNetworkProposal = address(proposal);

        unlockedFor = address(proposal);
        gov.createProposal.value(msg.value)(address(proposal));
        unlockedFor = address(0);
    }
}

File 2 of 22 : 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 3 of 22 : 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 4 of 22 : ReentrancyGuard.sol
pragma solidity ^0.5.0;
import "./Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 */
contract ReentrancyGuard is Initializable {
    // counter to allow mutex lock with only one SSTORE operation
    uint256 private _guardCounter;

    function initialize() internal initializer {
        // The counter starts at one to prevent changing it from zero to a non-zero
        // value, which is a more expensive operation.
        _guardCounter = 1;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _guardCounter += 1;
        uint256 localCounter = _guardCounter;
        _;
        require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call");
    }

    uint256[50] private ______gap;
}

File 5 of 22 : 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 6 of 22 : Constants.sol
pragma solidity ^0.5.0;

import "../common/SafeMath.sol";
import "../common/Decimal.sol";

contract StatusConstants {
    enum Status {
        INITIAL,
        RESOLVED,
        FAILED
    }

    // bit map
    uint256 constant STATUS_INITIAL = 0;
    uint256 constant STATUS_RESOLVED = 1;
    uint256 constant STATUS_FAILED = 1 << 1;
    uint256 constant STATUS_CANCELED = 1 << 2;
    uint256 constant STATUS_EXECUTION_EXPIRED = 1 << 3;

    function statusInitial() internal pure returns (uint256) {
        return STATUS_INITIAL;
    }

    function statusExecutionExpired() internal pure returns (uint256) {
        return STATUS_EXECUTION_EXPIRED;
    }

    function statusFailed() internal pure returns (uint256) {
        return STATUS_FAILED;
    }

    function statusCanceled() internal pure returns (uint256) {
        return STATUS_CANCELED;
    }

    function statusResolved() internal pure returns (uint256) {
        return STATUS_RESOLVED;
    }

    function isInitialStatus(uint256 status) internal pure returns (bool) {
        return status == STATUS_INITIAL;
    }

    // task assignments
    uint256 constant TASK_VOTING = 1;
}

contract Constants is StatusConstants {
    using SafeMath for uint256;

    function minVotesAbsolute(uint256 totalWeight, uint256 minVotesRatio) public pure returns (uint256) {
        return totalWeight * minVotesRatio / Decimal.unit();
    }

    function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) {
        bytes memory bytesArray = new bytes(32);
        for (uint256 i; i < 32; i++) {
            bytesArray[i] = _bytes32[i];
        }
        return string(bytesArray);
    }
}

File 7 of 22 : Governance.sol
pragma solidity ^0.5.0;

import "../common/ReentrancyGuard.sol";
import "../common/SafeMath.sol";
import "../model/Governable.sol";
import "../proposal/base/IProposal.sol";
import "../verifiers/IProposalVerifier.sol";
import "../proposal/SoftwareUpgradeProposal.sol";
import "./Proposal.sol";
import "./Constants.sol";
import "./GovernanceSettings.sol";
import "./LRC.sol";
import "../version/Version.sol";
import "../votebook/votebook.sol";

contract Governance is Initializable, ReentrancyGuard, GovernanceSettings, Version {
    using SafeMath for uint256;
    using LRC for LRC.Option;

    struct Vote {
        uint256 weight;
        uint256[] choices;
    }

    struct ProposalState {
        Proposal.Parameters params;

        // voting state
        mapping(uint256 => LRC.Option) options;
        uint256 winnerOptionID;
        uint256 votes; // total weight of votes

        uint256 status;
    }

    struct Task {
        bool active;
        uint256 assignment;
        uint256 proposalID;
    }

    Governable governableContract;
    IProposalVerifier proposalVerifier;
    uint256 public lastProposalID;
    Task[] tasks;

    mapping(uint256 => ProposalState) proposals;
    mapping(address => mapping(uint256 => uint256)) public overriddenWeight; // voter address, proposalID -> weight
    mapping(address => mapping(address => mapping(uint256 => Vote))) _votes; // voter, delegationReceiver, proposalID -> Vote

    VotesBookKeeper votebook;

    event ProposalCreated(uint256 proposalID);
    event ProposalResolved(uint256 proposalID);
    event ProposalRejected(uint256 proposalID);
    event ProposalCanceled(uint256 proposalID);
    event ProposalExecutionExpired(uint256 proposalID);
    event TasksHandled(uint256 startIdx, uint256 endIdx, uint256 handled);
    event TasksErased(uint256 quantity);
    event VoteWeightOverridden(address voter, uint256 diff);
    event VoteWeightUnOverridden(address voter, uint256 diff);
    event Voted(address voter, address delegatedTo, uint256 proposalID, uint256[] choices, uint256 weight);
    event VoteCanceled(address voter, address delegatedTo, uint256 proposalID);

    function initialize(address _governableContract, address _proposalVerifier, address _votebook) public initializer {
        ReentrancyGuard.initialize();
        governableContract = Governable(_governableContract);
        proposalVerifier = IProposalVerifier(_proposalVerifier);
        votebook = VotesBookKeeper(_votebook);
    }

    function proposalParams(uint256 proposalID) public view returns (uint256 pType, Proposal.ExecType executable, uint256 minVotes, uint256 minAgreement, uint256[] memory opinionScales, bytes32[] memory options, address proposalContract, uint256 votingStartTime, uint256 votingMinEndTime, uint256 votingMaxEndTime) {
        Proposal.Parameters memory p = proposals[proposalID].params;
        return (p.pType, p.executable, p.minVotes, p.minAgreement, p.opinionScales, p.options, p.proposalContract, p.deadlines.votingStartTime, p.deadlines.votingMinEndTime, p.deadlines.votingMaxEndTime);
    }

    function proposalOptionState(uint256 proposalID, uint256 optionID) public view returns (uint256 votes, uint256 agreementRatio, uint256 agreement) {
        ProposalState storage prop = proposals[proposalID];
        LRC.Option storage opt = prop.options[optionID];
        return (opt.votes, LRC.agreementRatio(opt), opt.agreement);
    }

    function proposalState(uint256 proposalID) public view returns (uint256 winnerOptionID, uint256 votes, uint256 status) {
        ProposalState memory p = proposals[proposalID];
        return (p.winnerOptionID, p.votes, p.status);
    }

    function getVote(address from, address delegatedTo, uint256 proposalID) public view returns (uint256 weight, uint256[] memory choices) {
        Vote memory v = _votes[from][delegatedTo][proposalID];
        return (v.weight, v.choices);
    }

    function tasksCount() public view returns (uint256) {
        return (tasks.length);
    }

    function getTask(uint256 i) public view returns (bool active, uint256 assignment, uint256 proposalID) {
        Task memory t = tasks[i];
        return (t.active, t.assignment, t.proposalID);
    }

    function vote(address delegatedTo, uint256 proposalID, uint256[] calldata choices) nonReentrant external {
        if (delegatedTo == address(0)) {
            delegatedTo = msg.sender;
        }

        ProposalState storage prop = proposals[proposalID];

        require(prop.params.proposalContract != address(0), "proposal with a given ID doesnt exist");
        require(isInitialStatus(prop.status), "proposal isn't active");
        require(block.timestamp >= prop.params.deadlines.votingStartTime, "proposal voting has't begun");
        require(_votes[msg.sender][delegatedTo][proposalID].weight == 0, "vote already exists");
        require(choices.length == prop.params.options.length, "wrong number of choices");

        uint256 weight = _processNewVote(proposalID, msg.sender, delegatedTo, choices);
        require(weight != 0, "zero weight");
    }

    function createProposal(address proposalContract) nonReentrant external payable {
        require(msg.value == proposalFee(), "paid proposal fee is wrong");

        lastProposalID++;
        _createProposal(lastProposalID, proposalContract);
        addTasks(lastProposalID);

        // burn a non-reward part of the proposal fee
        burn(proposalBurntFee());

        emit ProposalCreated(lastProposalID);
    }

    function _createProposal(uint256 proposalID, address proposalContract) internal {
        require(proposalContract != address(0), "empty proposal address");
        IProposal p = IProposal(proposalContract);
        // capture the parameters once to ensure that contract will not return different values
        uint256 pType = p.pType();
        Proposal.ExecType executable = p.executable();
        uint256 minVotes = p.minVotes();
        uint256 minAgreement = p.minAgreement();
        uint256[] memory opinionScales = p.opinionScales();
        uint256 votingStartTime = p.votingStartTime();
        uint256 votingMinEndTime = p.votingMinEndTime();
        uint256 votingMaxEndTime = p.votingMaxEndTime();
        bytes32[] memory options = p.options();
        // check the parameters and contract
        require(options.length != 0, "proposal options are empty - nothing to vote for");
        require(options.length <= maxOptions(), "too many options");
        bool ok;
        ok = proposalVerifier.verifyProposalParams(pType, executable, minVotes, minAgreement, opinionScales, votingStartTime, votingMinEndTime, votingMaxEndTime);
        require(ok, "proposal parameters failed verification");
        ok = proposalVerifier.verifyProposalContract(pType, proposalContract);
        require(ok, "proposal contract failed verification");
        // save the parameters
        ProposalState storage prop = proposals[proposalID];
        prop.params.pType = pType;
        prop.params.executable = executable;
        prop.params.minVotes = minVotes;
        prop.params.minAgreement = minAgreement;
        prop.params.opinionScales = opinionScales;
        prop.params.proposalContract = proposalContract;
        prop.params.deadlines.votingStartTime = votingStartTime;
        prop.params.deadlines.votingMinEndTime = votingMinEndTime;
        prop.params.deadlines.votingMaxEndTime = votingMaxEndTime;
        prop.params.options = options;
    }

    // cancelProposal cancels the proposal if no one managed to vote yet
    // must be sent from the proposal contract
    function cancelProposal(uint256 proposalID) nonReentrant external {
        ProposalState storage prop = proposals[proposalID];
        require(prop.params.proposalContract != address(0), "proposal with a given ID doesnt exist");
        require(isInitialStatus(prop.status), "proposal isn't active");
        require(prop.votes == 0, "voting has already begun");
        require(msg.sender == prop.params.proposalContract, "must be sent from the proposal contract");

        prop.status = statusCanceled();
        emit ProposalCanceled(proposalID);
    }

    // handleTasks triggers proposal deadlines processing for a specified range of tasks
    function handleTasks(uint256 startIdx, uint256 quantity) nonReentrant external {
        uint256 handled = 0;
        uint256 i;
        for (i = startIdx; i < tasks.length && i < startIdx + quantity; i++) {
            if (handleTask(i)) {
                handled += 1;
            }
        }

        require(handled != 0, "no tasks handled");

        emit TasksHandled(startIdx, i, handled);
        // reward the sender
        msg.sender.transfer(handled.mul(taskHandlingReward()));
    }

    // tasksCleanup erases inactive (handled) tasks backwards until an active task is met
    function tasksCleanup(uint256 quantity) nonReentrant external {
        uint256 erased;
        for (erased = 0; tasks.length > 0 && erased < quantity; erased++) {
            if (!tasks[tasks.length - 1].active) {
                tasks.length--;
            } else {
                break;
                // stop when first active task was met
            }
        }
        require(erased > 0, "no tasks erased");
        emit TasksErased(erased);
        // reward the sender
        msg.sender.transfer(erased.mul(taskErasingReward()));
    }

    // handleTask calls handleTaskAssignments and marks task as inactive if it was handled
    function handleTask(uint256 taskIdx) internal returns (bool handled) {
        require(taskIdx < tasks.length, "incorrect task index");
        Task storage task = tasks[taskIdx];
        if (!task.active) {
            return false;
        }
        handled = handleTaskAssignments(tasks[taskIdx].proposalID, task.assignment);
        if (handled) {
            task.active = false;
        }
        return handled;
    }

    // handleTaskAssignments iterates through assignment types and calls a specific handler
    function handleTaskAssignments(uint256 proposalID, uint256 assignment) internal returns (bool handled) {
        ProposalState storage prop = proposals[proposalID];
        if (!isInitialStatus(prop.status)) {
            // deactivate all tasks for non-active proposals
            return true;
        }
        if (assignment == TASK_VOTING) {
            return handleVotingTask(proposalID, prop);
        }
        return false;
    }

    // handleVotingTask handles only TASK_VOTING
    function handleVotingTask(uint256 proposalID, ProposalState storage prop) internal returns (bool handled) {
        uint256 minVotesAbs = minVotesAbsolute(governableContract.getTotalWeight(), prop.params.minVotes);
        bool must = block.timestamp >= prop.params.deadlines.votingMaxEndTime;
        bool may = block.timestamp >= prop.params.deadlines.votingMinEndTime && prop.votes >= minVotesAbs;
        if (!must && !may) {
            return false;
        }
        (bool proposalResolved, uint256 winnerID) = _calculateVotingTally(prop);
        if (proposalResolved) {
            (bool ok, bool expired) = executeProposal(prop, winnerID);
            if (!ok) {
                return false;
            }
            if (!expired) {
                prop.status = statusResolved();
                prop.winnerOptionID = winnerID;
                emit ProposalResolved(proposalID);
            } else {
                prop.status = statusExecutionExpired();
                emit ProposalExecutionExpired(proposalID);
            }
        } else {
            prop.status = statusFailed();
            emit ProposalRejected(proposalID);
        }
        return true;
    }

    function executeProposal(ProposalState storage prop, uint256 winnerOptionID) internal returns (bool, bool) {
        bool executable = prop.params.executable == Proposal.ExecType.CALL || prop.params.executable == Proposal.ExecType.DELEGATECALL;
        if (!executable) {
            return (true, false);
        }

        bool executionExpired = block.timestamp > prop.params.deadlines.votingMaxEndTime + maxExecutionPeriod();
        if (executionExpired) {
            // protection against proposals which revert or consume too much gas
            return (true, true);
        }
        address propAddr = prop.params.proposalContract;
        bool success;
        bytes memory result;
        if (prop.params.executable == Proposal.ExecType.CALL) {
            (success, result) = propAddr.call(abi.encodeWithSignature("execute_call(uint256)", winnerOptionID));
        } else {
            (success, result) = propAddr.delegatecall(abi.encodeWithSignature("execute_delegatecall(address,uint256)", propAddr, winnerOptionID));
        }
        result;
        return (success, false);
    }

    function _calculateVotingTally(ProposalState storage prop) internal view returns (bool, uint256) {
        uint256 minVotesAbs = minVotesAbsolute(governableContract.getTotalWeight(), prop.params.minVotes);
        uint256 mostAgreement = 0;
        uint256 winnerID = prop.params.options.length;
        if (prop.votes < minVotesAbs) {
            return (false, winnerID);
        }
        for (uint256 i = 0; i < prop.params.options.length; i++) {
            uint256 optionID = i;
            uint256 agreement = LRC.agreementRatio(prop.options[optionID]);

            if (agreement < prop.params.minAgreement) {
                // critical resistance against this option
                continue;
            }

            if (mostAgreement == 0 || agreement > mostAgreement) {
                mostAgreement = agreement;
                winnerID = i;
            }
        }

        return (winnerID != prop.params.options.length, winnerID);
    }

    // calculateVotingTally calculates the voting tally and returns {is finished, won option ID, total weight of votes}
    function calculateVotingTally(uint256 proposalID) external view returns (bool proposalResolved, uint256 winnerID, uint256 votes) {
        ProposalState storage prop = proposals[proposalID];
        (proposalResolved, winnerID) = _calculateVotingTally(prop);
        return (proposalResolved, winnerID, prop.votes);
    }

    function cancelVote(address delegatedTo, uint256 proposalID) nonReentrant external {
        if (delegatedTo == address(0)) {
            delegatedTo = msg.sender;
        }
        Vote memory v = _votes[msg.sender][delegatedTo][proposalID];
        require(v.weight != 0, "doesn't exist");
        require(isInitialStatus(proposals[proposalID].status), "proposal isn't active");
        _cancelVote(msg.sender, delegatedTo, proposalID);
    }

    function _cancelVote(address voter, address delegatedTo, uint256 proposalID) internal {
        Vote storage v = _votes[voter][delegatedTo][proposalID];
        if (v.weight == 0) {
            return;
        }

        if (voter != delegatedTo) {
            unOverrideDelegationWeight(delegatedTo, proposalID, v.weight);
        }

        removeChoicesFromProp(proposalID, v.choices, v.weight);
        delete _votes[voter][delegatedTo][proposalID];

        if (address(votebook) != address(0)) {
            votebook.onVoteCanceled(voter, delegatedTo, proposalID);
        }

        emit VoteCanceled(voter, delegatedTo, proposalID);
    }

    function makeVote(uint256 proposalID, address voter, address delegatedTo, uint256[] memory choices, uint256 weight) internal {
        _votes[voter][delegatedTo][proposalID] = Vote(weight, choices);
        addChoicesToProp(proposalID, choices, weight);

        if (address(votebook) != address(0)) {
            votebook.onVoted(voter, delegatedTo, proposalID);
        }

        emit Voted(voter, delegatedTo, proposalID, choices, weight);
    }

    function _processNewVote(uint256 proposalID, address voterAddr, address delegatedTo, uint256[] memory choices) internal returns (uint256) {
        if (delegatedTo == voterAddr) {
            // voter isn't a delegator
            uint256 weight = governableContract.getReceivedWeight(voterAddr);
            uint256 overridden = overriddenWeight[voterAddr][proposalID];
            if (weight > overridden) {
                weight -= overridden;
            } else {
                weight = 0;
            }
            if (weight == 0) {
                return 0;
            }
            makeVote(proposalID, voterAddr, voterAddr, choices, weight);
            return weight;
        } else {
            if (_votes[delegatedTo][delegatedTo][proposalID].choices.length > 0) {
                // recount vote from delegatedTo
                // Needed only in a case if delegatedTo's received weight has changed without calling recountVote
                _recountVote(delegatedTo, delegatedTo, proposalID);
            }
            // votes through one of delegations, overrides previous vote of "delegatedTo" (if any)
            uint256 delegatedWeight = governableContract.getWeight(voterAddr, delegatedTo);
            // reduce weight of vote of "delegatedTo" (current vote or any future vote)
            overrideDelegationWeight(delegatedTo, proposalID, delegatedWeight);
            if (delegatedWeight == 0) {
                return 0;
            }
            // make own vote
            makeVote(proposalID, voterAddr, delegatedTo, choices, delegatedWeight);
            return delegatedWeight;
        }
    }

    function recountVote(address voterAddr, address delegatedTo, uint256 proposalID) nonReentrant external {
        Vote storage v = _votes[voterAddr][delegatedTo][proposalID];
        Vote storage vSuper = _votes[delegatedTo][delegatedTo][proposalID];
        require(v.choices.length > 0, "doesn't exist");
        require(isInitialStatus(proposals[proposalID].status), "proposal isn't active");
        uint256 beforeSelf = v.weight;
        uint256 beforeSuper = vSuper.weight;
        _recountVote(voterAddr, delegatedTo, proposalID);
        uint256 afterSelf = v.weight;
        uint256 afterSuper = vSuper.weight;
        // check that some weight has changed due to recounting
        require(beforeSelf != afterSelf || beforeSuper != afterSuper, "nothing changed");
    }

    function _recountVote(address voterAddr, address delegatedTo, uint256 proposalID) internal returns (uint256) {
        uint256[] memory origChoices = _votes[voterAddr][delegatedTo][proposalID].choices;
        // cancel previous vote
        _cancelVote(voterAddr, delegatedTo, proposalID);
        // re-make vote
        return _processNewVote(proposalID, voterAddr, delegatedTo, origChoices);
    }

    function overrideDelegationWeight(address delegatedTo, uint256 proposalID, uint256 weight) internal {
        uint256 overridden = overriddenWeight[delegatedTo][proposalID];
        overridden = overridden.add(weight);
        overriddenWeight[delegatedTo][proposalID] = overridden;
        Vote storage v = _votes[delegatedTo][delegatedTo][proposalID];
        if (v.choices.length > 0) {
            v.weight = v.weight.sub(weight);
            removeChoicesFromProp(proposalID, v.choices, weight);
        }
        emit VoteWeightOverridden(delegatedTo, weight);
    }

    function unOverrideDelegationWeight(address delegatedTo, uint256 proposalID, uint256 weight) internal {
        uint256 overridden = overriddenWeight[delegatedTo][proposalID];
        overridden = overridden.sub(weight);
        overriddenWeight[delegatedTo][proposalID] = overridden;
        Vote storage v = _votes[delegatedTo][delegatedTo][proposalID];
        if (v.choices.length > 0) {
            v.weight = v.weight.add(weight);
            addChoicesToProp(proposalID, v.choices, weight);
        }
        emit VoteWeightUnOverridden(delegatedTo, weight);
    }

    function addChoicesToProp(uint256 proposalID, uint256[] memory choices, uint256 weight) internal {
        ProposalState storage prop = proposals[proposalID];

        prop.votes = prop.votes.add(weight);

        for (uint256 i = 0; i < prop.params.options.length; i++) {
            prop.options[i].addVote(choices[i], weight, prop.params.opinionScales);
        }
    }

    function removeChoicesFromProp(uint256 proposalID, uint256[] memory choices, uint256 weight) internal {
        ProposalState storage prop = proposals[proposalID];

        prop.votes = prop.votes.sub(weight);

        for (uint256 i = 0; i < prop.params.options.length; i++) {
            prop.options[i].removeVote(choices[i], weight, prop.params.opinionScales);
        }
    }

    function addTasks(uint256 proposalID) internal {
        tasks.push(Task(true, TASK_VOTING, proposalID));
    }

    function burn(uint256 amount) internal {
        address(0).transfer(amount);
    }

    function sanitizeWinnerID(uint256 proposalID) external {
        ProposalState storage prop = proposals[proposalID];
        require(prop.status == STATUS_RESOLVED, "proposal isn't resolved");
        require(prop.params.executable == Proposal.ExecType.NONE, "proposal is executable");
        require(prop.winnerOptionID == 0, "winner ID is correct");
        (, prop.winnerOptionID) = _calculateVotingTally(prop);
    }

    function upgrade(address _votebook) external {
        require(address(votebook) == address(0), "already set");
        votebook = VotesBookKeeper(_votebook);
        // erase leftovers from upgradeability proxy
        assembly {
            sstore(0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103, 0)
            sstore(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, 0)
        }
    }
}

File 8 of 22 : GovernanceSettings.sol
pragma solidity ^0.5.0;

import "../common/Decimal.sol";
import "../common/SafeMath.sol";
import "../model/Governable.sol";
import "../proposal/SoftwareUpgradeProposal.sol";
import "./Constants.sol";

/**
 * @dev Various constants for governance governance settings
 */
contract GovernanceSettings is Constants {
    uint256 constant _proposalFee = _proposalBurntFee + _taskHandlingReward + _taskErasingReward;
    uint256 constant _proposalBurntFee = 50 * 1e18;
    uint256 constant _taskHandlingReward = 40 * 1e18;
    uint256 constant _taskErasingReward = 10 * 1e18;
    uint256 constant _maxOptions = 10;
    uint256 constant _maxExecutionPeriod = 3 days;

    // @dev proposalFee is the fee for a proposal
    function proposalFee() public pure returns (uint256) {
        return _proposalFee;
    }

    // @dev proposalBurntFee is the burnt part of fee for a proposal
    function proposalBurntFee() public pure returns (uint256) {
        return _proposalBurntFee;
    }

    // @dev taskHandlingReward is a reward for handling each task
    function taskHandlingReward() public pure returns (uint256) {
        return _taskHandlingReward;
    }

    // @dev taskErasingReward is a reward for erasing each task
    function taskErasingReward() public pure returns (uint256) {
        return _taskErasingReward;
    }

    // @dev maxOptions maximum number of options to choose
    function maxOptions() public pure returns (uint256) {
        return _maxOptions;
    }

    // maxExecutionPeriod is maximum time for which proposal is executable after maximum voting end date
    function maxExecutionPeriod() public pure returns (uint256) {
        return _maxExecutionPeriod;
    }
}

File 9 of 22 : LRC.sol
pragma solidity ^0.5.0;

import "../common/Decimal.sol";
import "../common/SafeMath.sol";

/**
 * @dev LRC implements the "least resistant consensus" paper. More detailed description can be found in Fantom's docs.
 */
library LRC {
    using SafeMath for uint256;

    struct Option {
        uint256 votes;
        uint256 agreement;
    }

    // agreementRatio is a ratio of option agreement (higher -> option is less supported)
    function agreementRatio(Option storage self) internal view returns (uint256) {
        if (self.votes == 0) {
            // avoid division by zero
            return 0;
        }
        return self.agreement.mul(Decimal.unit()).div(self.votes);
    }

    function maxAgreementScale(uint256[] storage opinionScales) internal view returns (uint256) {
        return opinionScales[opinionScales.length - 1];
    }

    function addVote(Option storage self, uint256 opinionID, uint256 weight, uint256[] storage opinionScales) internal {
        require(opinionID < opinionScales.length, "wrong opinion ID");

        uint256 scale = opinionScales[opinionID];

        self.votes = self.votes.add(weight);
        self.agreement = self.agreement.add(weight.mul(scale).div(maxAgreementScale(opinionScales)));
    }

    function removeVote(Option storage self, uint256 opinionID, uint256 weight, uint256[] storage opinionScales) internal {
        require(opinionID < opinionScales.length, "wrong opinion ID");

        uint256 scale = opinionScales[opinionID];

        self.votes = self.votes.sub(weight);
        self.agreement = self.agreement.sub(weight.mul(scale).div(maxAgreementScale(opinionScales)));
    }
}

File 10 of 22 : Proposal.sol
pragma solidity ^0.5.0;

import "../proposal/base/IProposal.sol";

library Proposal {
    struct Timeline {
        uint256 votingStartTime; // date when the voting starts
        uint256 votingMinEndTime; // date of earliest possible voting end
        uint256 votingMaxEndTime; // date of latest possible voting end
    }

    enum ExecType {
        NONE,
        CALL,
        DELEGATECALL
    }

    struct Parameters {
        uint256 pType; // type of proposal (e.g. plaintext, software upgrade)
        ExecType executable; // proposal execution type when proposal gets resolved
        uint256 minVotes; // min. quorum (ratio)
        // minAgreement is the minimum acceptable ratio of agreement for an option.
        // It's guaranteed not to win otherwise.
        uint256 minAgreement; // min. agreement threshold for options (ratio)
        uint256[] opinionScales;
        address proposalContract; // contract which stores the proposal data and executes its logic
        bytes32[] options;
        Timeline deadlines;
    }
}

File 11 of 22 : Governable.sol
pragma solidity ^0.5.0;

/**
 * @dev Governable defines the main interface for all governable items
 */
interface Governable {
    // Gets the total weight of voters
    function getTotalWeight() external view returns (uint256);

    // Gets the received delegated weight
    function getReceivedWeight(address addr) external view returns (uint256);

    // Gets the voting weight which is delegated from the specified address to the specified address
    function getWeight(address from, address to) external view returns (uint256);
}

File 12 of 22 : Ownable.sol
pragma solidity ^0.5.0;

import "../common/Initializable.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be aplied to your functions to restrict their use to
 * the owner.
 */
contract Ownable is Initializable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function initialize(address sender) internal initializer {
        _owner = sender;
        emit OwnershipTransferred(address(0), _owner);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * > Note: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }

    uint256[50] private ______gap;
}

File 13 of 22 : BaseProposal.sol
pragma solidity ^0.5.0;

import "../../common/SafeMath.sol";
import "./IProposal.sol";
import "../../verifiers/IProposalVerifier.sol";
import "../../governance/Proposal.sol";

/**
 * @dev A base for any proposal
 */
contract BaseProposal is IProposal {
    using SafeMath for uint256;

    string _name;
    string _description;
    bytes32[] _options;

    uint256 _minVotes;
    uint256 _minAgreement;
    uint256[] _opinionScales;

    uint256 _start;
    uint256 _minEnd;
    uint256 _maxEnd;

    // verifyProposalParams passes proposal parameters to a given verifier
    function verifyProposalParams(address verifier) public view returns (bool) {
        IProposalVerifier proposalVerifier = IProposalVerifier(verifier);
        return proposalVerifier.verifyProposalParams(pType(), executable(), minVotes(), minAgreement(), opinionScales(), votingStartTime(), votingMinEndTime(), votingMaxEndTime());
    }

    function pType() public view returns (uint256) {
        require(false, "must be overridden");
        return uint256(StdProposalTypes.NOT_INIT);
    }

    function executable() public view returns (Proposal.ExecType) {
        require(false, "must be overridden");
        return Proposal.ExecType.NONE;
    }

    function minVotes() public view returns (uint256) {
        return _minVotes;
    }

    function minAgreement() public view returns (uint256) {
        return _minAgreement;
    }

    function opinionScales() public view returns (uint256[] memory) {
        return _opinionScales;
    }

    function options() public view returns (bytes32[] memory) {
        return _options;
    }

    function votingStartTime() public view returns (uint256) {
        return block.timestamp + _start;
    }

    function votingMinEndTime() public view returns (uint256) {
        return votingStartTime() + _minEnd;
    }

    function votingMaxEndTime() public view returns (uint256) {
        return votingStartTime() + _maxEnd;
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function description() public view returns (string memory) {
        return _description;
    }

    function execute_delegatecall(address, uint256) external {
        require(false, "not delegatecall-executable");
    }

    function execute_call(uint256) external {
        require(false, "not call-executable");
    }
}

File 14 of 22 : Cancelable.sol
pragma solidity ^0.5.0;

import "../../ownership/Ownable.sol";
import "../../governance/Governance.sol";

contract Cancelable is Ownable {
    constructor() public {
        Ownable.initialize(msg.sender);
    }

    function cancel(uint256 myID, address govAddress) external onlyOwner {
        Governance gov = Governance(govAddress);
        gov.cancelProposal(myID);
    }
}

File 15 of 22 : DelegatecallExecutableProposal.sol
pragma solidity ^0.5.0;

import "./BaseProposal.sol";
import "../../governance/Proposal.sol";

contract DelegatecallExecutableProposal is BaseProposal {
    // Returns execution type
    function executable() public view returns (Proposal.ExecType) {
        return Proposal.ExecType.DELEGATECALL;
    }

    function pType() public view returns (uint256) {
        return uint256(StdProposalTypes.UNKNOWN_DELEGATECALL_EXECUTABLE);
    }

    function execute_delegatecall(address, uint256) external {
        require(false, "must be overridden");
    }
}

File 16 of 22 : IProposal.sol
pragma solidity ^0.5.0;

import "../../governance/Proposal.sol";

/**
 * @dev An abstract proposal
 */
contract IProposal {
    // Get type of proposal (e.g. plaintext, software upgrade)
    function pType() external view returns (uint256);
    // Proposal execution type when proposal gets resolved
    function executable() external view returns (Proposal.ExecType);
    // Get min. turnout (ratio)
    function minVotes() external view returns (uint256);
    // Get min. agreement for options (ratio)
    function minAgreement() external view returns (uint256);
    // Get scales for opinions
    function opinionScales() external view returns (uint256[] memory);
    // Get options to choose from
    function options() external view returns (bytes32[] memory);
    // Get date when the voting starts
    function votingStartTime() external view returns (uint256);
    // Get date of earliest possible voting end
    function votingMinEndTime() external view returns (uint256);
    // Get date of latest possible voting end
    function votingMaxEndTime() external view returns (uint256);

    // execute proposal logic on approval (if executable == call)
    // Called via call opcode from governance contract
    function execute_call(uint256 optionID) external;

    // execute proposal logic on approval (if executable == delegatecall)
    // Called via delegatecall opcode from governance contract, hence selfAddress is provided
    function execute_delegatecall(address selfAddress, uint256 optionID) external;

    // Get human-readable name
    function name() external view returns (string memory);
    // Get human-readable description
    function description() external view returns (string memory);

    // Standard proposal types. The standard may be outdated, actual proposal templates may differ
    enum StdProposalTypes {
        NOT_INIT,
        UNKNOWN_NON_EXECUTABLE,
        UNKNOWN_CALL_EXECUTABLE,
        UNKNOWN_DELEGATECALL_EXECUTABLE
    }
}

File 17 of 22 : NetworkParameterProposal.sol
pragma solidity ^0.5.0;

import "./base/Cancelable.sol";
import "./base/DelegatecallExecutableProposal.sol";

interface ConstsI {
    function updateMinSelfStake(uint256 v) external;

    function updateMaxDelegatedRatio(uint256 v) external;

    function updateValidatorCommission(uint256 v) external;

    function updateBurntFeeShare(uint256 v) external; // 4

    function updateTreasuryFeeShare(uint256 v) external;

    function updateUnlockedRewardRatio(uint256 v) external;

    function updateMinLockupDuration(uint256 v) external;

    function updateMaxLockupDuration(uint256 v) external; // 8

    function updateWithdrawalPeriodEpochs(uint256 v) external;

    function updateWithdrawalPeriodTime(uint256 v) external;

    function updateBaseRewardPerSecond(uint256 v) external;

    function updateOfflinePenaltyThresholdTime(uint256 v) external; // 12

    function updateOfflinePenaltyThresholdBlocksNum(uint256 v) external;

    function updateTargetGasPowerPerSecond(uint256 v) external;

    function updateGasPriceBalancingCounterweight(uint256 v) external; // 15
}

/**
 * @dev NetworkParameterProposal proposal
 */
contract NetworkParameterProposal is DelegatecallExecutableProposal, Cancelable {
    using SafeMath for uint256;
    Proposal.ExecType _exec;
    ConstsI public consts;
    uint8 public methodID;
    uint256[] public getOptionVal;

    constructor(
        string memory __description,
        uint8 __methodID,
        uint256[] memory __optionsVals,
        address __consts,
        uint256 __minVotes, uint256 __minAgreement, uint256 __start, uint256 __minEnd, uint256 __maxEnd,
        address verifier
    ) public {
        require(__methodID >= 1 && __methodID <= 15, "wrong methodID");
        if (__methodID == 1) {
            _name = "Update minimum self-stake";
            _options = uintsToStrs(__optionsVals, 1e18, " FTM");
        } else if (__methodID == 2) {
            _name = "Update maximum delegated stake ratio";
            _options = uintsToStrs(__optionsVals, 1e16, " %");
        } else if (__methodID == 3) {
            _name = "Update validator rewards commission";
            _options = uintsToStrs(__optionsVals, 1e16, " %");
        } else if (__methodID == 4) {
            _name = "Update burnt fee share";
            _options = uintsToStrs(__optionsVals, 1e16, " %");
        } else if (__methodID == 5) {
            _name = "Update treasury fee share";
            _options = uintsToStrs(__optionsVals, 1e16, " %");
        } else if (__methodID == 6) {
            _name = "Update unlocked reward ratio";
            _options = uintsToStrs(__optionsVals, 1e16, " %");
        } else if (__methodID == 7) {
            _name = "Update minimum lockup duration";
            _options = uintsToStrs(__optionsVals, 1440 minutes, " days");
        } else if (__methodID == 8) {
            _name = "Update maximum lockup duration";
            _options = uintsToStrs(__optionsVals, 1440 minutes, " days");
        } else if (__methodID == 9) {
            _name = "Update number epochs of withdrawal period";
            _options = uintsToStrs(__optionsVals, 1, "");
        } else if (__methodID == 10) {
            _name = "Update withdrawal period";
            _options = uintsToStrs(__optionsVals, 60 minutes, " hours");
        } else if (__methodID == 11) {
            _name = "Update base reward per second";
            _options = uintsToStrs(__optionsVals, 1e18, " FTM");
        } else if (__methodID == 12) {
            _name = "Update time threshold for offline penalty";
            _options = uintsToStrs(__optionsVals, 60 minutes, " hours");
        } else if (__methodID == 13) {
            _name = "Update blocks threshold for offline penalty";
            _options = uintsToStrs(__optionsVals, 1, "");
        } else if (__methodID == 14) {
            _name = "Update target gas power second";
            _options = uintsToStrs(__optionsVals, 1e6, " M");
        } else {
            _name = "Update gas price balancing period";
            _options = uintsToStrs(__optionsVals, 1 minutes, " minutes");
        }
        _description = __description;
        methodID = __methodID;
        _minVotes = __minVotes;
        _minAgreement = __minAgreement;
        _start = __start;
        _minEnd = __minEnd;
        _maxEnd = __maxEnd;
        getOptionVal = __optionsVals;
        _opinionScales = [0, 1, 2, 3, 4];
        consts = ConstsI(__consts);
        // verify the proposal right away to avoid deploying a wrong proposal
        if (verifier != address(0)) {
            require(verifyProposalParams(verifier), "failed verification");
        }
    }

    function pType() public view returns (uint256) {
        // return 6003;
        return 4;
    }

    function optionVals() external view returns (uint256[] memory) {
        return getOptionVal;
    }

    event NetworkParameterUpgradeIsDone(uint256 newValue);

    function execute_delegatecall(address selfAddr, uint256 winnerOptionID) external {
        NetworkParameterProposal self = NetworkParameterProposal(selfAddr);
        uint256 __methodID = self.methodID();

        if (__methodID == 1) {
            self.consts().updateMinSelfStake(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 2) {
            self.consts().updateMaxDelegatedRatio(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 3) {
            self.consts().updateValidatorCommission(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 4) {
            self.consts().updateBurntFeeShare(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 5) {
            self.consts().updateTreasuryFeeShare(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 6) {
            self.consts().updateUnlockedRewardRatio(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 7) {
            self.consts().updateMinLockupDuration(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 8) {
            self.consts().updateMaxLockupDuration(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 9) {
            self.consts().updateWithdrawalPeriodEpochs(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 10) {
            self.consts().updateWithdrawalPeriodTime(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 11) {
            self.consts().updateBaseRewardPerSecond(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 12) {
            self.consts().updateOfflinePenaltyThresholdTime(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 13) {
            self.consts().updateOfflinePenaltyThresholdBlocksNum(self.getOptionVal(winnerOptionID));
        } else if (__methodID == 14) {
            self.consts().updateTargetGasPowerPerSecond(self.getOptionVal(winnerOptionID));
        } else {
            self.consts().updateGasPriceBalancingCounterweight(self.getOptionVal(winnerOptionID));
        }

        emit NetworkParameterUpgradeIsDone(self.getOptionVal(winnerOptionID));
    }

    function decimalsNum(uint256 num) internal pure returns (uint256) {
        uint decimals;
        while (num != 0) {
            decimals++;
            num /= 10;
        }
        return decimals;
    }

    function uint256ToB(uint256 num) internal pure returns (bytes memory) {
        if (num == 0) {
            return bytes("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 bstr;
    }

    function uint256ToStr(uint256 num) internal pure returns (string memory) {
        return string(uint256ToB(num));
    }

    function decimalToStr(uint256 interger, uint256 fractional) internal pure returns (string memory) {
        bytes memory intStr = uint256ToB(interger);
        bytes memory fraStr = uint256ToB(fractional);
        // replace leading 1 with .
        fraStr[0] = byte(uint8(46));
        return string(abi.encodePacked(intStr, fraStr));
    }

    function unpackDecimal(uint256 num, uint256 unit) internal pure returns (uint256 interger, uint256 fractional) {
        assert(unit <= 1e18);
        fractional = (num % unit).mul(1e18).div(unit);
        return (num / unit, trimFractional(1e18 + fractional));
    }

    function trimFractional(uint256 fractional) internal pure returns (uint256) {
        if (fractional == 0) {
            return 0;
        }
        while (fractional % 10 == 0) {
            fractional /= 10;
        }
        return fractional;
    }

    function uintsToStrs(uint256[] memory vals, uint256 unit, string memory symbol) internal pure returns (bytes32[] memory) {
        bytes32[] memory res = new bytes32[](vals.length);
        for (uint256 i = 0; i < vals.length; i++) {
            (uint256 interger, uint256 fractional) = unpackDecimal(vals[i], unit);
            if (fractional == 1) {
                res[i] = strToB32(string(abi.encodePacked(uint256ToStr(interger), symbol)));
            } else {
                res[i] = strToB32(string(abi.encodePacked(decimalToStr(interger, fractional), symbol)));
            }
        }
        return res;
    }

    function strToB32(string memory str) internal pure returns (bytes32 result) {
        bytes memory tempEmptyStringTest = bytes(str);
        require(tempEmptyStringTest.length <= 32, "string is too long");
        if (tempEmptyStringTest.length == 0) {
            return 0x0;
        }
        assembly {
            result := mload(add(tempEmptyStringTest, 32))
        }
    }
}

File 18 of 22 : SoftwareUpgradeProposal.sol
pragma solidity ^0.5.0;

import "./base/Cancelable.sol";
import "./base/DelegatecallExecutableProposal.sol";

/**
 * @dev An interface to update this contract to a destination address
 */
interface Upgradability {
    function upgradeTo(address newImplementation) external;
}

/**
 * @dev SoftwareUpgrade proposal
 */
contract SoftwareUpgradeProposal is DelegatecallExecutableProposal, Cancelable {
    address public upgradeableContract;
    address public newImplementation;

    constructor(string memory __name, string memory __description,
        uint256 __minVotes, uint256 __minAgreement, uint256 __start, uint256 __minEnd, uint256 __maxEnd,
        address __upgradeableContract, address __newImplementation, address verifier) public {
        _name = __name;
        _description = __description;
        _options.push(bytes32("Level of agreement"));
        _minVotes = __minVotes;
        _minAgreement = __minAgreement;
        _opinionScales = [0, 1, 2, 3, 4];
        _start = __start;
        _minEnd = __minEnd;
        _maxEnd = __maxEnd;
        upgradeableContract = __upgradeableContract;
        newImplementation = __newImplementation;
        // verify the proposal right away to avoid deploying a wrong proposal
        if (verifier != address(0)) {
            require(verifyProposalParams(verifier), "failed verification");
        }
    }

    function execute_delegatecall(address selfAddr, uint256) external {
        SoftwareUpgradeProposal self = SoftwareUpgradeProposal(selfAddr);
        Upgradability(self.upgradeableContract()).upgradeTo(self.newImplementation());
    }
}

File 19 of 22 : IProposalVerifier.sol
pragma solidity ^0.5.0;

import "../governance/Proposal.sol";

/**
 * @dev A verifier can verify a proposal's inputs such as proposal parameters and proposal contract.
 */
interface IProposalVerifier {
    // Verifies proposal parameters with respect to the stored template of same type
    function verifyProposalParams(uint256 pType, Proposal.ExecType executable, uint256 minVotes, uint256 minAgreement, uint256[] calldata opinionScales, uint256 start, uint256 minEnd, uint256 maxEnd) external view returns (bool);

    // Verifies proposal contract of the specified type and address
    function verifyProposalContract(uint256 pType, address propAddr) external view returns (bool);
}

File 20 of 22 : ScopedVerifier.sol
pragma solidity ^0.5.0;

import "./IProposalVerifier.sol";
import "../governance/Governance.sol";

contract ScopedVerifier is IProposalVerifier {
    address internal unlockedFor;

    // verifyProposalParams checks proposal parameters
    function verifyProposalParams(uint256, Proposal.ExecType, uint256, uint256, uint256[] calldata, uint256, uint256, uint256) external view returns (bool) {
        return true;
    }

    // verifyProposalContract verifies proposal creator
    function verifyProposalContract(uint256, address propAddr) external view returns (bool) {
        return propAddr == unlockedFor;
    }
}

File 21 of 22 : Version.sol
pragma solidity ^0.5.0;

/**
 * @dev The version info of this contract
 */
contract Version {
    /**
     * @dev Returns the version of this contract.
     */
    function version() public pure returns (bytes4) {
        // version 00.0.2
        return "0002";
    }
}

File 22 of 22 : votebook.sol
pragma solidity ^0.5.0;

import "../ownership/Ownable.sol";

interface GovernanceI {
    function recountVote(address voterAddr, address delegatedTo, uint256 proposalID) external;

    function proposalState(uint256 proposalID) external view returns (uint256 winnerOptionID, uint256 votes, uint256 status);
}

contract VotesBookKeeper is Initializable, Ownable {
    address gov;

    uint256 public maxProposalsPerVoter;

    // voter, delegatedTo -> []proposal IDs
    mapping(address => mapping(address => uint256[])) votesList;

    // voter, delegatedTo, proposal ID -> {index in the list + 1}
    mapping(address => mapping(address => mapping(uint256 => uint256))) votesIndex;

    function initialize(address _owner, address _gov, uint256 _maxProposalsPerVoter) public initializer {
        Ownable.initialize(_owner);
        gov = _gov;
        maxProposalsPerVoter = _maxProposalsPerVoter;
    }

    function getProposalIDs(address voter, address delegatedTo) public view returns (uint256[] memory) {
        return votesList[voter][delegatedTo];
    }

    // returns vote index plus 1 if vote exists. Returns 0 if vote doesn't exist
    function getVoteIndex(address voter, address delegatedTo, uint256 proposalID) public view returns (uint256) {
        return votesIndex[voter][delegatedTo][proposalID];
    }

    function recountVotes(address voter, address delegatedTo) public {
        uint256[] storage list = votesList[voter][delegatedTo];
        uint256 origLen = list.length;
        uint256 i = 0;
        for (uint256 iter = 0; iter < origLen; iter++) {
            (bool success,) = gov.call(abi.encodeWithSignature("recountVote(address,address,uint256)", voter, delegatedTo, list[i]));
            bool evicted = false;
            if (!success) {
                // unindex if proposal isn't active
                (,, uint256 status) = GovernanceI(gov).proposalState(list[i]);
                if (status != 0) {
                    eraseVote(voter, delegatedTo, list[i], i + 1);
                    evicted = true;
                }
            }
            if (!evicted) {
                i++;
            }
        }
    }

    function onVoted(address voter, address delegatedTo, uint256 proposalID) external {
        uint256 idx = votesIndex[voter][delegatedTo][proposalID];
        if (idx > 0) {
            return;
        }
        if (votesList[voter][delegatedTo].length >= maxProposalsPerVoter) {
            // erase votes for outdated proposals
            recountVotes(voter, delegatedTo);
        }
        votesList[voter][delegatedTo].push(proposalID);
        idx = votesList[voter][delegatedTo].length;
        require(idx <= maxProposalsPerVoter, "too many votes");
        votesIndex[voter][delegatedTo][proposalID] = idx;
    }

    function onVoteCanceled(address voter, address delegatedTo, uint256 proposalID) external {
        uint256 idx = votesIndex[voter][delegatedTo][proposalID];
        if (idx == 0) {
            return;
        }
        eraseVote(voter, delegatedTo, proposalID, idx);
    }

    function eraseVote(address voter, address delegatedTo, uint256 proposalID, uint256 idx) internal {
        votesIndex[voter][delegatedTo][proposalID] = 0;
        uint256[] storage list = votesList[voter][delegatedTo];
        uint256 len = list.length;
        if (len == idx) {
            // last element
            list.length--;
        } else {
            uint256 last = list[len - 1];
            list[idx - 1] = last;
            list.length--;
            votesIndex[voter][delegatedTo][last] = idx;
        }
    }

    function setMaxProposalsPerVoter(uint256 v) onlyOwner external {
        maxProposalsPerVoter = v;
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"address","name":"_constsAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":false,"inputs":[{"internalType":"string","name":"__description","type":"string"},{"internalType":"uint8","name":"__methodID","type":"uint8"},{"internalType":"uint256[]","name":"__optionVals","type":"uint256[]"},{"internalType":"uint256","name":"__minVotes","type":"uint256"},{"internalType":"uint256","name":"__minAgreement","type":"uint256"},{"internalType":"uint256","name":"__start","type":"uint256"},{"internalType":"uint256","name":"__minEnd","type":"uint256"},{"internalType":"uint256","name":"__maxEnd","type":"uint256"}],"name":"create","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"lastNetworkProposal","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"propAddr","type":"address"}],"name":"verifyProposalContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"enum Proposal.ExecType","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"verifyProposalParams","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405260043610620000445760003560e01c80632b6103bb146200004957806384d1113c146200007d578063d294ed2814620001d5578063f3f4ef791462000226575b600080fd5b3480156200005657600080fd5b5062000061620002d2565b604080516001600160a01b039092168252519081900360200190f35b620001d360048036036101008110156200009657600080fd5b810190602081018135640100000000811115620000b257600080fd5b820183602082011115620000c557600080fd5b80359060200191846001830284011164010000000083111715620000e857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929560ff8535169590949093506040810192506020013590506401000000008111156200014757600080fd5b8201836020820111156200015a57600080fd5b803590602001918460208302840111640100000000831117156200017d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505082359350505060208101359060408101359060608101359060800135620002e1565b005b348015620001e257600080fd5b506200021260048036036040811015620001fb57600080fd5b50803590602001356001600160a01b03166200054b565b604080519115158252519081900360200190f35b3480156200023357600080fd5b506200021260048036036101008110156200024d57600080fd5b81359160ff6020820135169160408201359160608101359181019060a0810160808201356401000000008111156200028457600080fd5b8201836020820111156200029757600080fd5b80359060200191846020830284011164010000000083111715620002ba57600080fd5b91935091508035906020810135906040013562000561565b6003546001600160a01b031681565b6000888888600260009054906101000a90046001600160a01b031689898989896000604051620003119062000570565b80806020018b60ff1660ff168152602001806020018a6001600160a01b03166001600160a01b03168152602001898152602001888152602001878152602001868152602001858152602001846001600160a01b03166001600160a01b0316815260200183810383528d818151815260200191508051906020019080838360005b83811015620003ab57818101518382015260200162000391565b50505050905090810190601f168015620003d95780820380516001836020036101000a031916815260200191505b5083810382528b5181528b51602091820191808e01910280838360005b8381101562000410578181015183820152602001620003f6565b505050509050019c50505050505050505050505050604051809103906000f08015801562000442573d6000803e3d6000fd5b506040805163f2fde38b60e01b815233600482015290519192506001600160a01b0383169163f2fde38b9160248082019260009290919082900301818387803b1580156200048f57600080fd5b505af1158015620004a4573d6000803e3d6000fd5b5050600380546001600160a01b038086166001600160a01b031992831681179093556000805490921683178255600154604080516307eecaf560e01b8152600481019590955251911694506307eecaf593503492602480820193929182900301818588803b1580156200051657600080fd5b505af11580156200052b573d6000803e3d6000fd5b5050600080546001600160a01b0319169055505050505050505050505050565b6000546001600160a01b03908116911614919050565b60019998505050505050505050565b613000806200057f8339019056fe60806040523480156200001157600080fd5b50604051620030003803806200300083398181016040526101408110156200003857600080fd5b81019080805160405193929190846401000000008211156200005957600080fd5b9083019060208201858111156200006f57600080fd5b82516401000000008111828201881017156200008a57600080fd5b82525081516020918201929091019080838360005b83811015620000b95781810151838201526020016200009f565b50505050905090810190601f168015620000e75780820380516001836020036101000a031916815260200191505b506040818152602083015192018051929491939192846401000000008211156200011057600080fd5b9083019060208201858111156200012657600080fd5b82518660208202830111640100000000821117156200014457600080fd5b82525081516020918201928201910280838360005b838110156200017357818101518382015260200162000159565b50505050919091016040908152602083810151918401516060850151608086015160a087015160c088015160e090980151959950929750909590945090929091620001c9903390620017db62000943821b17901c565b60018960ff1610158015620001e25750600f8960ff1611155b62000225576040805162461bcd60e51b815260206004820152600e60248201526d1ddc9bdb99c81b595d1a1bd9125160921b604482015290519081900360640190fd5b8860ff1660011415620002cd576040805180820190915260198082527f557064617465206d696e696d756d2073656c662d7374616b650000000000000060209092019182526200027891600091620012db565b50620002b088670de0b6b3a7640000604051806040016040528060048152602001632046544d60e01b81525062000a4660201b60201c565b8051620002c6916002916020909101906200135c565b5062000805565b8860ff16600214156200033f5760405180606001604052806024815260200162002fbb6024913980516200030a91600091602090910190620012db565b50620002b088662386f26fc1000060405180604001604052806002815260200161202560f01b81525062000a4660201b60201c565b8860ff16600314156200037c5760405180606001604052806023815260200162002f6a6023913980516200030a91600091602090910190620012db565b8860ff1660041415620003cf576040805180820190915260168082527f557064617465206275726e74206665652073686172650000000000000000000060209092019182526200030a91600091620012db565b8860ff166005141562000422576040805180820190915260198082527f557064617465207472656173757279206665652073686172650000000000000060209092019182526200030a91600091620012db565b8860ff1660061415620004755760408051808201909152601c8082527f55706461746520756e6c6f636b65642072657761726420726174696f0000000060209092019182526200030a91600091620012db565b8860ff1660071415620004fc5760408051808201909152601e8082527f557064617465206d696e696d756d206c6f636b7570206475726174696f6e00006020909201918252620004c891600091620012db565b50620002b0886201518060405180604001604052806005815260200164206461797360d81b81525062000a4660201b60201c565b8860ff16600814156200054f5760408051808201909152601e8082527f557064617465206d6178696d756d206c6f636b7570206475726174696f6e00006020909201918252620004c891600091620012db565b8860ff1660091415620005b05760405180606001604052806029815260200162002ef76029913980516200058c91600091602090910190620012db565b50620002b08860016040518060200160405280600081525062000a4660201b60201c565b8860ff16600a141562000637576040805180820190915260188082527f557064617465207769746864726177616c20706572696f64000000000000000060209092019182526200060391600091620012db565b50620002b088610e106040518060400160405280600681526020016520686f75727360d01b81525062000a4660201b60201c565b8860ff16600b14156200068a5760408051808201909152601d8082527f55706461746520626173652072657761726420706572207365636f6e6400000060209092019182526200027891600091620012db565b8860ff16600c1415620006c75760405180606001604052806029815260200162002f206029913980516200060391600091602090910190620012db565b8860ff16600d141562000704576040518060600160405280602b815260200162002ecc602b913980516200058c91600091602090910190620012db565b8860ff16600e1415620007885760408051808201909152601e8082527f557064617465207461726765742067617320706f776572207365636f6e64000060209092019182526200075791600091620012db565b50620002b088620f424060405180604001604052806002815260200161204d60f01b81525062000a4660201b60201c565b60405180606001604052806021815260200162002fdf602191398051620007b891600091602090910190620012db565b50620007ed88603c60405180604001604052806008815260200167206d696e7574657360c01b81525062000a4660201b60201c565b805162000803916002916020909101906200135c565b505b89516200081a9060019060208d0190620012db565b50606f805460ff60a81b1916600160a81b60ff8c1602179055600386905560048590556006849055600783905560088290558751620008619060709060208b01906200135c565b506040805160a081018252600081526001602082015260029181019190915260036060820152600460808201526200089d906005908162001399565b50606f80546001600160a01b03808a1661010002610100600160a81b0319909216919091179091558116156200093357620008e1816001600160e01b0362000bfa16565b62000933576040805162461bcd60e51b815260206004820152601360248201527f6661696c656420766572696669636174696f6e00000000000000000000000000604482015290519081900360640190fd5b50505050505050505050620013f9565b600954610100900460ff1680620009685750620009686001600160e01b0362000d9016565b8062000977575060095460ff16155b620009b45760405162461bcd60e51b815260040180806020018281038252602e81526020018062002f8d602e913960400191505060405180910390fd5b600954610100900460ff16158015620009e0576009805460ff1961ff0019909116610100171660011790555b603c80546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801562000a42576009805461ff00191690555b5050565b606080845160405190808252806020026020018201604052801562000a75578160200160208202803883390190505b50905060005b855181101562000bf15760008062000aae88848151811062000a9957fe5b60200260200101518862000d9760201b60201c565b91509150806001141562000bb35762000b9462000ad4836001600160e01b0362000e2816565b876040516020018083805190602001908083835b6020831062000b095780518252601f19909201916020918201910162000ae8565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062000b535780518252601f19909201916020918201910162000b32565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405262000e4460201b60201c565b84848151811062000ba157fe5b60200260200101818152505062000be6565b62000bcc62000ad483836001600160e01b0362000eb416565b84848151811062000bd957fe5b6020026020010181815250505b505060010162000a7b565b50949350505050565b6000816001600160a01b03811663f3f4ef7962000c1f6001600160e01b0362000fce16565b62000c326001600160e01b0362000fd316565b62000c456001600160e01b0362000fd816565b62000c586001600160e01b0362000fde16565b62000c6b6001600160e01b0362000fe416565b62000c7e6001600160e01b036200103e16565b62000c916001600160e01b036200104616565b62000ca46001600160e01b036200106516565b6040518963ffffffff1660e01b81526004018089815260200188600281111562000cca57fe5b60ff16815260200187815260200186815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b8381101562000d2e57818101518382015260200162000d14565b50505050905001995050505050505050505060206040518083038186803b15801562000d5957600080fd5b505afa15801562000d6e573d6000803e3d6000fd5b505050506040513d602081101562000d8557600080fd5b50519150505b919050565b303b155b90565b600080670de0b6b3a764000083111562000dad57fe5b62000df28362000dde670de0b6b3a764000086888162000dc957fe5b066200107e60201b620018cd1790919060201c565b620010e360201b6200192f1790919060201c565b905082848162000dfe57fe5b0462000e1d670de0b6b3a764000083016001600160e01b036200112d16565b915091509250929050565b606062000e3e826001600160e01b036200115716565b92915050565b6000606082905060208151111562000e98576040805162461bcd60e51b8152602060048201526012602482015271737472696e6720697320746f6f206c6f6e6760701b604482015290519081900360640190fd5b805162000eaa57506000905062000d8b565b6020015192915050565b60608062000ecb846001600160e01b036200115716565b9050606062000ee3846001600160e01b036200115716565b9050602e60f81b8160008151811062000ef857fe5b60200101906001600160f81b031916908160001a90535081816040516020018083805190602001908083835b6020831062000f455780518252601f19909201916020918201910162000f24565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062000f8f5780518252601f19909201916020918201910162000f6e565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529250505092915050565b600490565b600290565b60035490565b60045490565b606060058054806020026020016040519081016040528092919081815260200182805480156200103457602002820191906000526020600020905b8154815260200190600101908083116200101f575b5050505050905090565b600654420190565b6007546000906200105f6001600160e01b036200103e16565b01905090565b6008546000906200105f6001600160e01b036200103e16565b6000826200108f5750600062000e3e565b828202828482816200109d57fe5b0414620010dc5760405162461bcd60e51b815260040180806020018281038252602181526020018062002f496021913960400191505060405180910390fd5b9392505050565b6000620010dc83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200121a60201b60201c565b6000816200113e5750600062000d8b565b600a82066200115357600a820491506200113e565b5090565b6060816200117e57506040805180820190915260018152600360fc1b602082015262000d8b565b600062001194836001600160e01b03620012c116565b90506060816040519080825280601f01601f191660200182016040528015620011c4576020820181803883390190505b50905060001982015b84156200121257600a850660300160f81b828281518110620011eb57fe5b60200101906001600160f81b031916908160001a905350600a8504945060001901620011cd565b509392505050565b60008183620012aa5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156200126e57818101518382015260200162001254565b50505050905090810190601f1680156200129c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581620012b757fe5b0495945050505050565b6000805b821562000e3e57600101600a83049250620012c5565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200131e57805160ff19168380011785556200134e565b828001600101855582156200134e579182015b828111156200134e57825182559160200191906001019062001331565b5062001153929150620013dc565b8280548282559060005260206000209081019282156200134e57916020028201828111156200134e57825182559160200191906001019062001331565b8280548282559060005260206000209081019282156200134e579160200282015b828111156200134e578251829060ff16905591602001919060010190620013ba565b62000d9491905b80821115620011535760008155600101620013e3565b611ac380620014096000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c8063715018a6116100c3578063a61e393a1161007c578063a61e393a14610355578063aa3daba91461035d578063cb00e7d314610389578063d86d744e146103af578063e6f94d55146103b7578063f2fde38b146103d55761014d565b8063715018a6146102e05780637284e416146102e857806389d5b8ea146102f05780638da5cb5b1461030d5780638f32d59b146103315780639b3a8a071461034d5761014d565b80632842f0c2116101155780632842f0c2146102755780633cc228fd1461027d57806357d682c41461028557806363012d01146102b35780636eb067a0146102d05780636f24f8a1146102d85761014d565b806306fdde03146101525780631069143a146101cf57806316131a18146102275780632019a60814610253578063216b91161461026d575b600080fd5b61015a6103fb565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561019457818101518382015260200161017c565b50505050905090810190601f1680156101c15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101d7610491565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102135781810151838201526020016101fb565b505050509050019250505060405180910390f35b61022f6104e8565b6040518082600281111561023f57fe5b60ff16815260200191505060405180910390f35b61025b6104ed565b60408051918252519081900360200190f35b61025b6104f5565b6101d76104fa565b61025b610550565b6102b16004803603604081101561029b57600080fd5b50803590602001356001600160a01b0316610556565b005b6102b1600480360360208110156102c957600080fd5b5035610617565b61025b61065d565b6101d7610663565b6102b16106b9565b61015a61075c565b61025b6004803603602081101561030657600080fd5b50356107bc565b6103156107da565b604080516001600160a01b039092168252519081900360200190f35b6103396107e9565b604080519115158252519081900360200190f35b61025b6107fa565b61025b61080d565b6102b16004803603604081101561037357600080fd5b506001600160a01b03813516906020013561081a565b6103396004803603602081101561039f57600080fd5b50356001600160a01b0316611583565b6103156116b9565b6103bf6116cd565b6040805160ff9092168252519081900360200190f35b6102b1600480360360208110156103eb57600080fd5b50356001600160a01b03166116dd565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104875780601f1061045c57610100808354040283529160200191610487565b820191906000526020600020905b81548152906001019060200180831161046a57829003601f168201915b5050505050905090565b6060600280548060200260200160405190810160405280929190818152602001828054801561048757602002820191906000526020600020905b8154815260200190600101908083116104cb575050505050905090565b600290565b600654420190565b600490565b6060607080548060200260200160405190810160405280929190818152602001828054801561048757602002820191906000526020600020908154815260200190600101908083116104cb575050505050905090565b60035490565b61055e6107e9565b6105af576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000819050806001600160a01b031663e0a8f6f5846040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156105fa57600080fd5b505af115801561060e573d6000803e3d6000fd5b50505050505050565b6040805162461bcd60e51b81526020600482015260136024820152726e6f742063616c6c2d65786563757461626c6560681b604482015290519081900360640190fd5b50565b60045490565b6060600580548060200260200160405190810160405280929190818152602001828054801561048757602002820191906000526020600020908154815260200190600101908083116104cb575050505050905090565b6106c16107e9565b610712576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b603c546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603c80546001600160a01b0319169055565b60018054604080516020601f600260001961010087891615020190951694909404938401819004810282018101909252828152606093909290918301828280156104875780601f1061045c57610100808354040283529160200191610487565b607081815481106107c957fe5b600091825260209091200154905081565b603c546001600160a01b031690565b603c546001600160a01b0316331490565b60006007546108076104ed565b01905090565b60006008546108076104ed565b60008290506000816001600160a01b031663e6f94d556040518163ffffffff1660e01b815260040160206040518083038186803b15801561085a57600080fd5b505afa15801561086e573d6000803e3d6000fd5b505050506040513d602081101561088457600080fd5b505160ff16905060018114156109d357816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156108cd57600080fd5b505afa1580156108e1573d6000803e3d6000fd5b505050506040513d60208110156108f757600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263866c4b1792908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b505afa158015610960573d6000803e3d6000fd5b505050506040513d602081101561097657600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156109b657600080fd5b505af11580156109ca573d6000803e3d6000fd5b505050506114db565b8060021415610a9457816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610a1557600080fd5b505afa158015610a29573d6000803e3d6000fd5b505050506040513d6020811015610a3f57600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b03928316926381ffcdf192908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060031415610b5557816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ad657600080fd5b505afa158015610aea573d6000803e3d6000fd5b505050506040513d6020811015610b0057600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692632ee7113292908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060041415610c1657816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b9757600080fd5b505afa158015610bab573d6000803e3d6000fd5b505050506040513d6020811015610bc157600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692632bb9fe8d92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060051415610cd757816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c5857600080fd5b505afa158015610c6c573d6000803e3d6000fd5b505050506040513d6020811015610c8257600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263f8d5177e92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060061415610d9857816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1957600080fd5b505afa158015610d2d573d6000803e3d6000fd5b505050506040513d6020811015610d4357600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692637945ef9992908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060071415610e5957816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610dda57600080fd5b505afa158015610dee573d6000803e3d6000fd5b505050506040513d6020811015610e0457600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263bf25338b92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060081415610f1a57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e9b57600080fd5b505afa158015610eaf573d6000803e3d6000fd5b505050506040513d6020811015610ec557600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263ad7b3f7b92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b8060091415610fdb57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f5c57600080fd5b505afa158015610f70573d6000803e3d6000fd5b505050506040513d6020811015610f8657600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692638f078bfa92908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600a141561109c57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561101d57600080fd5b505afa158015611031573d6000803e3d6000fd5b505050506040513d602081101561104757600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263455366a492908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600b141561115d57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110de57600080fd5b505afa1580156110f2573d6000803e3d6000fd5b505050506040513d602081101561110857600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263b6d9edd592908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600c141561121e57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561119f57600080fd5b505afa1580156111b3573d6000803e3d6000fd5b505050506040513d60208110156111c957600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692636348ebb892908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600d14156112df57816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561126057600080fd5b505afa158015611274573d6000803e3d6000fd5b505050506040513d602081101561128a57600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692632e84e8e692908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b80600e14156113a057816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b15801561132157600080fd5b505afa158015611335573d6000803e3d6000fd5b505050506040513d602081101561134b57600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b0392831692634332686792908616916389d5b8ea91602480820192602092909190829003018186803b15801561094c57600080fd5b816001600160a01b031663d86d744e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113d957600080fd5b505afa1580156113ed573d6000803e3d6000fd5b505050506040513d602081101561140357600080fd5b5051604080516344eadc7560e11b81526004810186905290516001600160a01b039283169263d3f48dbe92908616916389d5b8ea91602480820192602092909190829003018186803b15801561145857600080fd5b505afa15801561146c573d6000803e3d6000fd5b505050506040513d602081101561148257600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156114c257600080fd5b505af11580156114d6573d6000803e3d6000fd5b505050505b7f429f0e2ca73311a31e395b735e0bff6a88fb01c4f53b8dcdde0a6f208ee2f6ce826001600160a01b03166389d5b8ea856040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561154057600080fd5b505afa158015611554573d6000803e3d6000fd5b505050506040513d602081101561156a57600080fd5b505160408051918252519081900360200190a150505050565b6000816001600160a01b03811663f3f4ef7961159d6104f5565b6115a56104e8565b6115ad610550565b6115b561065d565b6115bd610663565b6115c56104ed565b6115cd6107fa565b6115d561080d565b6040518963ffffffff1660e01b8152600401808981526020018860028111156115fa57fe5b60ff16815260200187815260200186815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b8381101561165c578181015183820152602001611644565b50505050905001995050505050505050505060206040518083038186803b15801561168657600080fd5b505afa15801561169a573d6000803e3d6000fd5b505050506040513d60208110156116b057600080fd5b50519392505050565b606f5461010090046001600160a01b031681565b606f54600160a81b900460ff1681565b6116e56107e9565b611736576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61065a816001600160a01b03811661177f5760405162461bcd60e51b8152600401808060200182810382526026815260200180611a1a6026913960400191505060405180910390fd5b603c546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603c80546001600160a01b0319166001600160a01b0392909216919091179055565b600954610100900460ff16806117f457506117f4611971565b80611802575060095460ff16155b61183d5760405162461bcd60e51b815260040180806020018281038252602e815260200180611a61602e913960400191505060405180910390fd5b600954610100900460ff16158015611868576009805460ff1961ff0019909116610100171660011790555b603c80546001600160a01b0319166001600160a01b0384811691909117918290556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a380156118c9576009805461ff00191690555b5050565b6000826118dc57506000611929565b828202828482816118e957fe5b04146119265760405162461bcd60e51b8152600401808060200182810382526021815260200180611a406021913960400191505060405180910390fd5b90505b92915050565b600061192683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611977565b303b1590565b60008183611a035760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156119c85781810151838201526020016119b0565b50505050905090810190601f1680156119f55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581611a0f57fe5b049594505050505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564a265627a7a72315820d9717271113959374c09d444a1ba5eafcc9e63b058830c9d7dc03b72e8c0b14b64736f6c6343000511003255706461746520626c6f636b73207468726573686f6c6420666f72206f66666c696e652070656e616c7479557064617465206e756d6265722065706f636873206f66207769746864726177616c20706572696f645570646174652074696d65207468726573686f6c6420666f72206f66666c696e652070656e616c7479536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775570646174652076616c696461746f72207265776172647320636f6d6d697373696f6e436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564557064617465206d6178696d756d2064656c656761746564207374616b6520726174696f557064617465206761732070726963652062616c616e63696e6720706572696f64a265627a7a72315820e5a8126504e5adc65c22d0a64f04531f942f3b7928f32e565a6f49e44e7314d264736f6c63430005110032

Block Transaction 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

Transaction 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.