Address Details
contract

0x1690e229c37219F0a10E102232de5E2591dE7dF5

Contract Name
EpochRewards
Creator
0xe23a4c–2b2dee at 0xffa6a8–c64e0d
Balance
0 CELO ( )
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
452036
Contract name:
EpochRewards




Optimization enabled
false
Compiler version
v0.5.8+commit.23d335f2




Verified at
2020-04-22T21:53:05.889942Z

Contract source code

pragma solidity ^0.5.3;


library SafeMath {
    
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        
        
        
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        
        require(b > 0, errorMessage);
        uint256 c = a / b;
        

        return c;
    }

    
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

contract Context {
    
    
    constructor () internal { }
    

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; 
        return msg.data;
    }
}

contract Ownable is Context {
    address private _owner;

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

    
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    
    function owner() public view returns (address) {
        return _owner;
    }

    
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    
    function isOwner() public view returns (bool) {
        return _msgSender() == _owner;
    }

    
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

contract CalledByVm {
  modifier onlyVm() {
    require(msg.sender == address(0), "Only VM can call");
    _;
  }
}

library FixidityLib {
  struct Fraction {
    uint256 value;
  }

  
  function digits() internal pure returns (uint8) {
    return 24;
  }

  uint256 private constant FIXED1_UINT = 1000000000000000000000000;

  
  function fixed1() internal pure returns (Fraction memory) {
    return Fraction(FIXED1_UINT);
  }

  
  function wrap(uint256 x) internal pure returns (Fraction memory) {
    return Fraction(x);
  }

  
  function unwrap(Fraction memory x) internal pure returns (uint256) {
    return x.value;
  }

  
  function mulPrecision() internal pure returns (uint256) {
    return 1000000000000;
  }

  
  function maxNewFixed() internal pure returns (uint256) {
    return 115792089237316195423570985008687907853269984665640564;
  }

  
  function newFixed(uint256 x) internal pure returns (Fraction memory) {
    require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()");
    return Fraction(x * FIXED1_UINT);
  }

  
  function fromFixed(Fraction memory x) internal pure returns (uint256) {
    return x.value / FIXED1_UINT;
  }

  
  function newFixedFraction(uint256 numerator, uint256 denominator)
    internal
    pure
    returns (Fraction memory)
  {
    Fraction memory convertedNumerator = newFixed(numerator);
    Fraction memory convertedDenominator = newFixed(denominator);
    return divide(convertedNumerator, convertedDenominator);
  }

  
  function integer(Fraction memory x) internal pure returns (Fraction memory) {
    return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); 
  }

  
  function fractional(Fraction memory x) internal pure returns (Fraction memory) {
    return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); 
  }

  
  function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    uint256 z = x.value + y.value;
    require(z >= x.value, "add overflow detected");
    return Fraction(z);
  }

  
  function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    require(x.value >= y.value, "substraction underflow detected");
    return Fraction(x.value - y.value);
  }

  
  function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    if (x.value == 0 || y.value == 0) return Fraction(0);
    if (y.value == FIXED1_UINT) return x;
    if (x.value == FIXED1_UINT) return y;

    
    
    uint256 x1 = integer(x).value / FIXED1_UINT;
    uint256 x2 = fractional(x).value;
    uint256 y1 = integer(y).value / FIXED1_UINT;
    uint256 y2 = fractional(y).value;

    
    uint256 x1y1 = x1 * y1;
    if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected");

    
    
    uint256 fixed_x1y1 = x1y1 * FIXED1_UINT;
    if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected");
    x1y1 = fixed_x1y1;

    uint256 x2y1 = x2 * y1;
    if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected");

    uint256 x1y2 = x1 * y2;
    if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected");

    x2 = x2 / mulPrecision();
    y2 = y2 / mulPrecision();
    uint256 x2y2 = x2 * y2;
    if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected");

    
    Fraction memory result = Fraction(x1y1);
    result = add(result, Fraction(x2y1)); 
    result = add(result, Fraction(x1y2)); 
    result = add(result, Fraction(x2y2)); 
    return result;
  }

  
  function reciprocal(Fraction memory x) internal pure returns (Fraction memory) {
    require(x.value != 0, "can't call reciprocal(0)");
    return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); 
  }

  
  function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    require(y.value != 0, "can't divide by 0");
    uint256 X = x.value * FIXED1_UINT;
    require(X / FIXED1_UINT == x.value, "overflow at divide");
    return Fraction(X / y.value);
  }

  
  function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value > y.value;
  }

  
  function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value >= y.value;
  }

  
  function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value < y.value;
  }

  
  function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value <= y.value;
  }

  
  function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value == y.value;
  }

  
  function isProperFraction(Fraction memory x) internal pure returns (bool) {
    return lte(x, fixed1());
  }
}

interface IERC20 {
    
    function totalSupply() external view returns (uint256);

    
    function balanceOf(address account) external view returns (uint256);

    
    function transfer(address recipient, uint256 amount) external returns (bool);

    
    function allowance(address owner, address spender) external view returns (uint256);

    
    function approve(address spender, uint256 amount) external returns (bool);

    
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    
    event Transfer(address indexed from, address indexed to, uint256 value);

    
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IAccounts {
  function isAccount(address) external view returns (bool);
  function voteSignerToAccount(address) external view returns (address);
  function validatorSignerToAccount(address) external view returns (address);
  function attestationSignerToAccount(address) external view returns (address);
  function signerToAccount(address) external view returns (address);
  function getAttestationSigner(address) external view returns (address);
  function getValidatorSigner(address) external view returns (address);
  function getVoteSigner(address) external view returns (address);
  function hasAuthorizedVoteSigner(address) external view returns (bool);
  function hasAuthorizedValidatorSigner(address) external view returns (bool);
  function hasAuthorizedAttestationSigner(address) external view returns (bool);

  function setAccountDataEncryptionKey(bytes calldata) external;
  function setMetadataURL(string calldata) external;
  function setName(string calldata) external;
  function setWalletAddress(address, uint8, bytes32, bytes32) external;
  function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external;

  function getDataEncryptionKey(address) external view returns (bytes memory);
  function getWalletAddress(address) external view returns (address);
  function getMetadataURL(address) external view returns (string memory);
  function batchGetMetadataURL(address[] calldata)
    external
    view
    returns (uint256[] memory, bytes memory);
  function getName(address) external view returns (string memory);

  function authorizeVoteSigner(address, uint8, bytes32, bytes32) external;
  function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external;
  function authorizeValidatorSignerWithPublicKey(address, uint8, bytes32, bytes32, bytes calldata)
    external;
  function authorizeValidatorSignerWithKeys(
    address,
    uint8,
    bytes32,
    bytes32,
    bytes calldata,
    bytes calldata,
    bytes calldata
  ) external;
  function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external;
  function createAccount() external returns (bool);
}

interface IFeeCurrencyWhitelist {
  function addToken(address) external;
  function getWhitelist() external view returns (address[] memory);
}

interface IFreezer {
  function isFrozen(address) external view returns (bool);
}

interface IRegistry {
  function setAddressFor(string calldata, address) external;
  function getAddressForOrDie(bytes32) external view returns (address);
  function getAddressFor(bytes32) external view returns (address);
  function isOneOf(bytes32[] calldata, address) external view returns (bool);
}

interface IElection {
  function getTotalVotes() external view returns (uint256);
  function getActiveVotes() external view returns (uint256);
  function getTotalVotesByAccount(address) external view returns (uint256);
  function markGroupIneligible(address) external;
  function markGroupEligible(address, address, address) external;
  function electValidatorSigners() external view returns (address[] memory);
  function vote(address, uint256, address, address) external returns (bool);
  function activate(address) external returns (bool);
  function revokeActive(address, uint256, address, address, uint256) external returns (bool);
  function revokeAllActive(address, address, address, uint256) external returns (bool);
  function revokePending(address, uint256, address, address, uint256) external returns (bool);
  function forceDecrementVotes(
    address,
    uint256,
    address[] calldata,
    address[] calldata,
    uint256[] calldata
  ) external returns (uint256);
}

interface IGovernance {
  function isVoting(address) external view returns (bool);
}

interface ILockedGold {
  function incrementNonvotingAccountBalance(address, uint256) external;
  function decrementNonvotingAccountBalance(address, uint256) external;
  function getAccountTotalLockedGold(address) external view returns (uint256);
  function getTotalLockedGold() external view returns (uint256);
  function getPendingWithdrawals(address)
    external
    view
    returns (uint256[] memory, uint256[] memory);
  function getTotalPendingWithdrawals(address) external view returns (uint256);
  function lock() external payable;
  function unlock(uint256) external;
  function relock(uint256, uint256) external;
  function withdraw(uint256) external;
  function slash(
    address account,
    uint256 penalty,
    address reporter,
    uint256 reward,
    address[] calldata lessers,
    address[] calldata greaters,
    uint256[] calldata indices
  ) external;
  function isSlasher(address) external view returns (bool);
}

interface IValidators {
  function getAccountLockedGoldRequirement(address) external view returns (uint256);
  function meetsAccountLockedGoldRequirements(address) external view returns (bool);
  function getGroupNumMembers(address) external view returns (uint256);
  function getGroupsNumMembers(address[] calldata) external view returns (uint256[] memory);
  function getNumRegisteredValidators() external view returns (uint256);
  function getTopGroupValidators(address, uint256) external view returns (address[] memory);
  function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool);
  function updatePublicKeys(address, address, bytes calldata, bytes calldata, bytes calldata)
    external
    returns (bool);
  function isValidator(address) external view returns (bool);
  function isValidatorGroup(address) external view returns (bool);
  function calculateGroupEpochScore(uint256[] calldata uptimes) external view returns (uint256);
  function groupMembershipInEpoch(address account, uint256 epochNumber, uint256 index)
    external
    view
    returns (address);
  function halveSlashingMultiplier(address group) external;
  function forceDeaffiliateIfValidator(address validator) external;
  function getValidatorGroupSlashingMultiplier(address) external view returns (uint256);
  function affiliate(address group) external returns (bool);
}

interface IRandom {
  function revealAndCommit(bytes32, bytes32, address) external;
  function randomnessBlockRetentionWindow() external view returns (uint256);
  function random() external view returns (bytes32);
  function getBlockRandomness(uint256) external view returns (bytes32);
}

interface IAttestations {
  function setAttestationRequestFee(address, uint256) external;
  function request(bytes32, uint256, address) external;
  function selectIssuers(bytes32) external;
  function complete(bytes32, uint8, bytes32, bytes32) external;
  function revoke(bytes32, uint256) external;
  function withdraw(address) external;

  function setAttestationExpiryBlocks(uint256) external;

  function getMaxAttestations() external view returns (uint256);

  function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address);
  function getAttestationRequestFee(address) external view returns (uint256);

  function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory);

  function getAttestationStats(bytes32, address) external view returns (uint32, uint32);

  function getAttestationState(bytes32, address, address)
    external
    view
    returns (uint8, uint32, address);
  function getCompletableAttestations(bytes32, address)
    external
    view
    returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory);
}

interface IExchange {
  function exchange(uint256, uint256, bool) external returns (uint256);
  function setUpdateFrequency(uint256) external;
  function getBuyTokenAmount(uint256, bool) external view returns (uint256);
  function getSellTokenAmount(uint256, bool) external view returns (uint256);
  function getBuyAndSellBuckets(bool) external view returns (uint256, uint256);
}

interface IReserve {
  function setTobinTaxStalenessThreshold(uint256) external;
  function addToken(address) external returns (bool);
  function removeToken(address, uint256) external returns (bool);
  function transferGold(address payable, uint256) external returns (bool);
  function transferExchangeGold(address payable, uint256) external returns (bool);
  function getReserveGoldBalance() external view returns (uint256);
  function getUnfrozenReserveGoldBalance() external view returns (uint256);
  function getOrComputeTobinTax() external returns (uint256, uint256);
  function getTokens() external view returns (address[] memory);
  function getReserveRatio() external view returns (uint256);
}

interface ISortedOracles {
  function addOracle(address, address) external;
  function removeOracle(address, address, uint256) external;
  function report(address, uint256, address, address) external;
  function removeExpiredReports(address, uint256) external;
  function isOldestReportExpired(address token) external view returns (bool, address);
  function numRates(address) external view returns (uint256);
  function medianRate(address) external view returns (uint256, uint256);
  function numTimestamps(address) external view returns (uint256);
  function medianTimestamp(address) external view returns (uint256);
}

interface IStableToken {
  function mint(address, uint256) external returns (bool);
  function burn(uint256) external returns (bool);
  function setInflationParameters(uint256, uint256) external;
  function valueToUnits(uint256) external view returns (uint256);
  function unitsToValue(uint256) external view returns (uint256);
  function getInflationParameters() external view returns (uint256, uint256, uint256, uint256);

  
  function balanceOf(address) external view returns (uint256);
}

contract UsingRegistry is Ownable {
  event RegistrySet(address indexed registryAddress);

  
  bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts"));
  bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations"));
  bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher"));
  bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256(
    abi.encodePacked("DoubleSigningSlasher")
  );
  bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election"));
  bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange"));
  bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256(
    abi.encodePacked("FeeCurrencyWhitelist")
  );
  bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer"));
  bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken"));
  bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance"));
  bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256(
    abi.encodePacked("GovernanceSlasher")
  );
  bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold"));
  bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve"));
  bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random"));
  bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles"));
  bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken"));
  bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators"));
  

  IRegistry public registry;

  modifier onlyRegisteredContract(bytes32 identifierHash) {
    require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract");
    _;
  }

  modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) {
    require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts");
    _;
  }

  
  function setRegistry(address registryAddress) public onlyOwner {
    require(registryAddress != address(0), "Cannot register the null address");
    registry = IRegistry(registryAddress);
    emit RegistrySet(registryAddress);
  }

  function getAccounts() internal view returns (IAccounts) {
    return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID));
  }

  function getAttestations() internal view returns (IAttestations) {
    return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID));
  }

  function getElection() internal view returns (IElection) {
    return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID));
  }

  function getExchange() internal view returns (IExchange) {
    return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID));
  }

  function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) {
    return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID));
  }

  function getFreezer() internal view returns (IFreezer) {
    return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID));
  }

  function getGoldToken() internal view returns (IERC20) {
    return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID));
  }

  function getGovernance() internal view returns (IGovernance) {
    return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID));
  }

  function getLockedGold() internal view returns (ILockedGold) {
    return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID));
  }

  function getRandom() internal view returns (IRandom) {
    return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID));
  }

  function getReserve() internal view returns (IReserve) {
    return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID));
  }

  function getSortedOracles() internal view returns (ISortedOracles) {
    return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));
  }

  function getStableToken() internal view returns (IStableToken) {
    return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID));
  }

  function getValidators() internal view returns (IValidators) {
    return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID));
  }
}

contract Freezable is UsingRegistry {
  
  
  modifier onlyWhenNotFrozen() {
    require(!getFreezer().isFrozen(address(this)), "can't call when contract is frozen");
    _;
  }
}

contract Initializable {
  bool public initialized;

  modifier initializer() {
    require(!initialized, "contract already initialized");
    initialized = true;
    _;
  }
}

contract UsingPrecompiles {
  using SafeMath for uint256;

  address constant TRANSFER = address(0xff - 2);
  address constant FRACTION_MUL = address(0xff - 3);
  address constant PROOF_OF_POSSESSION = address(0xff - 4);
  address constant GET_VALIDATOR = address(0xff - 5);
  address constant NUMBER_VALIDATORS = address(0xff - 6);
  address constant EPOCH_SIZE = address(0xff - 7);
  address constant BLOCK_NUMBER_FROM_HEADER = address(0xff - 8);
  address constant HASH_HEADER = address(0xff - 9);
  address constant GET_PARENT_SEAL_BITMAP = address(0xff - 10);
  address constant GET_VERIFIED_SEAL_BITMAP = address(0xff - 11);

  
  function fractionMulExp(
    uint256 aNumerator,
    uint256 aDenominator,
    uint256 bNumerator,
    uint256 bDenominator,
    uint256 exponent,
    uint256 _decimals
  ) public view returns (uint256, uint256) {
    require(aDenominator != 0 && bDenominator != 0, "a denominator is zero");
    uint256 returnNumerator;
    uint256 returnDenominator;
    bool success;
    bytes memory out;
    (success, out) = FRACTION_MUL.staticcall(
      abi.encodePacked(aNumerator, aDenominator, bNumerator, bDenominator, exponent, _decimals)
    );
    require(success, "error calling fractionMulExp precompile");
    returnNumerator = getUint256FromBytes(out, 0);
    returnDenominator = getUint256FromBytes(out, 32);
    return (returnNumerator, returnDenominator);
  }

  
  function getEpochSize() public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = EPOCH_SIZE.staticcall(abi.encodePacked());
    require(success, "error calling getEpochSize precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function getEpochNumberOfBlock(uint256 blockNumber) public view returns (uint256) {
    return epochNumberOfBlock(blockNumber, getEpochSize());
  }

  
  function getEpochNumber() public view returns (uint256) {
    return getEpochNumberOfBlock(block.number);
  }

  
  function epochNumberOfBlock(uint256 blockNumber, uint256 epochSize)
    internal
    pure
    returns (uint256)
  {
    
    uint256 epochNumber = blockNumber / epochSize;
    if (blockNumber % epochSize == 0) {
      return epochNumber;
    } else {
      return epochNumber + 1;
    }
  }

  
  function validatorSignerAddressFromCurrentSet(uint256 index) public view returns (address) {
    bytes memory out;
    bool success;
    (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, uint256(block.number)));
    require(success, "error calling validatorSignerAddressFromCurrentSet precompile");
    return address(getUint256FromBytes(out, 0));
  }

  
  function validatorSignerAddressFromSet(uint256 index, uint256 blockNumber)
    public
    view
    returns (address)
  {
    bytes memory out;
    bool success;
    (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, blockNumber));
    require(success, "error calling validatorSignerAddressFromSet precompile");
    return address(getUint256FromBytes(out, 0));
  }

  
  function numberValidatorsInCurrentSet() public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(uint256(block.number)));
    require(success, "error calling numberValidatorsInCurrentSet precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function numberValidatorsInSet(uint256 blockNumber) public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(blockNumber));
    require(success, "error calling numberValidatorsInSet precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function checkProofOfPossession(address sender, bytes memory blsKey, bytes memory blsPop)
    public
    view
    returns (bool)
  {
    bool success;
    (success, ) = PROOF_OF_POSSESSION.staticcall(abi.encodePacked(sender, blsKey, blsPop));
    return success;
  }

  
  function getBlockNumberFromHeader(bytes memory header) public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = BLOCK_NUMBER_FROM_HEADER.staticcall(abi.encodePacked(header));
    require(success, "error calling getBlockNumberFromHeader precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function hashHeader(bytes memory header) public view returns (bytes32) {
    bytes memory out;
    bool success;
    (success, out) = HASH_HEADER.staticcall(abi.encodePacked(header));
    require(success, "error calling hashHeader precompile");
    return getBytes32FromBytes(out, 0);
  }

  
  function getParentSealBitmap(uint256 blockNumber) public view returns (bytes32) {
    bytes memory out;
    bool success;
    (success, out) = GET_PARENT_SEAL_BITMAP.staticcall(abi.encodePacked(blockNumber));
    require(success, "error calling getParentSealBitmap precompile");
    return getBytes32FromBytes(out, 0);
  }

  
  function getVerifiedSealBitmapFromHeader(bytes memory header) public view returns (bytes32) {
    bytes memory out;
    bool success;
    (success, out) = GET_VERIFIED_SEAL_BITMAP.staticcall(abi.encodePacked(header));
    require(success, "error calling getVerifiedSealBitmapFromHeader precompile");
    return getBytes32FromBytes(out, 0);
  }

  
  function getUint256FromBytes(bytes memory bs, uint256 start) internal pure returns (uint256) {
    return uint256(getBytes32FromBytes(bs, start));
  }

  
  function getBytes32FromBytes(bytes memory bs, uint256 start) internal pure returns (bytes32) {
    require(bs.length >= start + 32, "slicing out of range");
    bytes32 x;
    assembly {
      x := mload(add(bs, add(start, 32)))
    }
    return x;
  }

  
  function minQuorumSize(uint256 blockNumber) public view returns (uint256) {
    return numberValidatorsInSet(blockNumber).mul(2).add(2).div(3);
  }

  
  function minQuorumSizeInCurrentSet() public view returns (uint256) {
    return minQuorumSize(block.number);
  }

}

contract EpochRewards is
  Ownable,
  Initializable,
  UsingPrecompiles,
  UsingRegistry,
  Freezable,
  CalledByVm
{
  using FixidityLib for FixidityLib.Fraction;
  using SafeMath for uint256;

  uint256 constant GENESIS_GOLD_SUPPLY = 600000000 ether; 
  uint256 constant GOLD_SUPPLY_CAP = 1000000000 ether; 
  uint256 constant YEARS_LINEAR = 15;
  uint256 constant SECONDS_LINEAR = YEARS_LINEAR * 365 * 1 days;

  
  
  struct RewardsMultiplierAdjustmentFactors {
    FixidityLib.Fraction underspend;
    FixidityLib.Fraction overspend;
  }

  
  
  
  
  
  
  struct RewardsMultiplierParameters {
    RewardsMultiplierAdjustmentFactors adjustmentFactors;
    
    FixidityLib.Fraction max;
  }

  
  struct TargetVotingYieldParameters {
    
    FixidityLib.Fraction target;
    
    
    FixidityLib.Fraction adjustmentFactor;
    
    FixidityLib.Fraction max;
  }

  uint256 public startTime = 0;
  RewardsMultiplierParameters private rewardsMultiplierParams;
  TargetVotingYieldParameters private targetVotingYieldParams;
  FixidityLib.Fraction private targetVotingGoldFraction;
  FixidityLib.Fraction private communityRewardFraction;
  FixidityLib.Fraction private carbonOffsettingFraction;
  address public carbonOffsettingPartner;
  uint256 public targetValidatorEpochPayment;

  event TargetVotingGoldFractionSet(uint256 fraction);
  event CommunityRewardFractionSet(uint256 fraction);
  event CarbonOffsettingFundSet(address indexed partner, uint256 fraction);
  event TargetValidatorEpochPaymentSet(uint256 payment);
  event TargetVotingYieldParametersSet(uint256 max, uint256 adjustmentFactor);
  event TargetVotingYieldSet(uint256 target);
  event RewardsMultiplierParametersSet(
    uint256 max,
    uint256 underspendAdjustmentFactor,
    uint256 overspendAdjustmentFactor
  );

  event TargetVotingYieldUpdated(uint256 fraction);

  
  function initialize(
    address registryAddress,
    uint256 targetVotingYieldInitial,
    uint256 targetVotingYieldMax,
    uint256 targetVotingYieldAdjustmentFactor,
    uint256 rewardsMultiplierMax,
    uint256 rewardsMultiplierUnderspendAdjustmentFactor,
    uint256 rewardsMultiplierOverspendAdjustmentFactor,
    uint256 _targetVotingGoldFraction,
    uint256 _targetValidatorEpochPayment,
    uint256 _communityRewardFraction,
    address _carbonOffsettingPartner,
    uint256 _carbonOffsettingFraction
  ) external initializer {
    _transferOwnership(msg.sender);
    setRegistry(registryAddress);
    setTargetVotingYieldParameters(targetVotingYieldMax, targetVotingYieldAdjustmentFactor);
    setRewardsMultiplierParameters(
      rewardsMultiplierMax,
      rewardsMultiplierUnderspendAdjustmentFactor,
      rewardsMultiplierOverspendAdjustmentFactor
    );
    setTargetVotingGoldFraction(_targetVotingGoldFraction);
    setTargetValidatorEpochPayment(_targetValidatorEpochPayment);
    setCommunityRewardFraction(_communityRewardFraction);
    setCarbonOffsettingFund(_carbonOffsettingPartner, _carbonOffsettingFraction);
    setTargetVotingYield(targetVotingYieldInitial);
    startTime = now;
  }

  
  function getTargetVotingYieldParameters() external view returns (uint256, uint256, uint256) {
    TargetVotingYieldParameters storage params = targetVotingYieldParams;
    return (params.target.unwrap(), params.max.unwrap(), params.adjustmentFactor.unwrap());
  }

  
  function getRewardsMultiplierParameters() external view returns (uint256, uint256, uint256) {
    RewardsMultiplierParameters storage params = rewardsMultiplierParams;
    return (
      params.max.unwrap(),
      params.adjustmentFactors.underspend.unwrap(),
      params.adjustmentFactors.overspend.unwrap()
    );
  }

  
  function setCommunityRewardFraction(uint256 value) public onlyOwner returns (bool) {
    require(value != communityRewardFraction.unwrap() && value < FixidityLib.fixed1().unwrap());
    communityRewardFraction = FixidityLib.wrap(value);
    emit CommunityRewardFractionSet(value);
    return true;
  }

  
  function getCommunityRewardFraction() external view returns (uint256) {
    return communityRewardFraction.unwrap();
  }

  
  function setCarbonOffsettingFund(address partner, uint256 value) public onlyOwner returns (bool) {
    require(partner != carbonOffsettingPartner || value != carbonOffsettingFraction.unwrap());
    require(value < FixidityLib.fixed1().unwrap());
    carbonOffsettingPartner = partner;
    carbonOffsettingFraction = FixidityLib.wrap(value);
    emit CarbonOffsettingFundSet(partner, value);
    return true;
  }

  
  function getCarbonOffsettingFraction() external view returns (uint256) {
    return carbonOffsettingFraction.unwrap();
  }

  
  function setTargetVotingGoldFraction(uint256 value) public onlyOwner returns (bool) {
    require(value != targetVotingGoldFraction.unwrap(), "Target voting gold fraction unchanged");
    require(
      value < FixidityLib.fixed1().unwrap(),
      "Target voting gold fraction cannot be larger than 1"
    );
    targetVotingGoldFraction = FixidityLib.wrap(value);
    emit TargetVotingGoldFractionSet(value);
    return true;
  }

  
  function getTargetVotingGoldFraction() external view returns (uint256) {
    return targetVotingGoldFraction.unwrap();
  }

  
  function setTargetValidatorEpochPayment(uint256 value) public onlyOwner returns (bool) {
    require(value != targetValidatorEpochPayment, "Target validator epoch payment unchanged");
    targetValidatorEpochPayment = value;
    emit TargetValidatorEpochPaymentSet(value);
    return true;
  }

  
  function setRewardsMultiplierParameters(
    uint256 max,
    uint256 underspendAdjustmentFactor,
    uint256 overspendAdjustmentFactor
  ) public onlyOwner returns (bool) {
    require(
      max != rewardsMultiplierParams.max.unwrap() ||
        overspendAdjustmentFactor != rewardsMultiplierParams.adjustmentFactors.overspend.unwrap() ||
        underspendAdjustmentFactor != rewardsMultiplierParams.adjustmentFactors.underspend.unwrap(),
      "Bad rewards multiplier parameters"
    );
    rewardsMultiplierParams = RewardsMultiplierParameters(
      RewardsMultiplierAdjustmentFactors(
        FixidityLib.wrap(underspendAdjustmentFactor),
        FixidityLib.wrap(overspendAdjustmentFactor)
      ),
      FixidityLib.wrap(max)
    );
    emit RewardsMultiplierParametersSet(max, underspendAdjustmentFactor, overspendAdjustmentFactor);
    return true;
  }

  
  function setTargetVotingYieldParameters(uint256 max, uint256 adjustmentFactor)
    public
    onlyOwner
    returns (bool)
  {
    require(
      max != targetVotingYieldParams.max.unwrap() ||
        adjustmentFactor != targetVotingYieldParams.adjustmentFactor.unwrap(),
      "Bad target voting yield parameters"
    );
    targetVotingYieldParams.max = FixidityLib.wrap(max);
    targetVotingYieldParams.adjustmentFactor = FixidityLib.wrap(adjustmentFactor);
    require(
      targetVotingYieldParams.max.lt(FixidityLib.fixed1()),
      "Max target voting yield must be lower than 100%"
    );
    emit TargetVotingYieldParametersSet(max, adjustmentFactor);
    return true;
  }

  
  function setTargetVotingYield(uint256 targetVotingYield) public onlyOwner returns (bool) {
    FixidityLib.Fraction memory target = FixidityLib.wrap(targetVotingYield);
    require(
      target.lte(targetVotingYieldParams.max),
      "Target voting yield must be less than or equal to max"
    );
    targetVotingYieldParams.target = target;
    emit TargetVotingYieldSet(targetVotingYield);
    return true;
  }

  
  function getTargetGoldTotalSupply() public view returns (uint256) {
    uint256 timeSinceInitialization = now.sub(startTime);
    if (timeSinceInitialization < SECONDS_LINEAR) {
      
      uint256 linearRewards = GOLD_SUPPLY_CAP.sub(GENESIS_GOLD_SUPPLY).div(2);
      uint256 targetRewards = linearRewards.mul(timeSinceInitialization).div(SECONDS_LINEAR);
      return targetRewards.add(GENESIS_GOLD_SUPPLY);
    } else {
      
      require(false, "Implement block reward calculation for years 15-30");
      return 0;
    }
  }

  
  function _getRewardsMultiplier(uint256 targetGoldSupplyIncrease)
    internal
    view
    returns (FixidityLib.Fraction memory)
  {
    uint256 targetSupply = getTargetGoldTotalSupply();
    uint256 totalSupply = getGoldToken().totalSupply();
    uint256 remainingSupply = GOLD_SUPPLY_CAP.sub(totalSupply.add(targetGoldSupplyIncrease));
    uint256 targetRemainingSupply = GOLD_SUPPLY_CAP.sub(targetSupply);
    FixidityLib.Fraction memory remainingToTargetRatio = FixidityLib
      .newFixed(remainingSupply)
      .divide(FixidityLib.newFixed(targetRemainingSupply));
    if (remainingToTargetRatio.gt(FixidityLib.fixed1())) {
      FixidityLib.Fraction memory delta = remainingToTargetRatio
        .subtract(FixidityLib.fixed1())
        .multiply(rewardsMultiplierParams.adjustmentFactors.underspend);
      FixidityLib.Fraction memory multiplier = FixidityLib.fixed1().add(delta);
      if (multiplier.lt(rewardsMultiplierParams.max)) {
        return multiplier;
      } else {
        return rewardsMultiplierParams.max;
      }
    } else if (remainingToTargetRatio.lt(FixidityLib.fixed1())) {
      FixidityLib.Fraction memory delta = FixidityLib
        .fixed1()
        .subtract(remainingToTargetRatio)
        .multiply(rewardsMultiplierParams.adjustmentFactors.overspend);
      if (delta.lt(FixidityLib.fixed1())) {
        return FixidityLib.fixed1().subtract(delta);
      } else {
        return FixidityLib.wrap(0);
      }
    } else {
      return FixidityLib.fixed1();
    }
  }

  
  function getTargetVoterRewards() public view returns (uint256) {
    return
      FixidityLib
        .newFixed(getElection().getActiveVotes())
        .multiply(targetVotingYieldParams.target)
        .fromFixed();
  }

  
  function getTargetTotalEpochPaymentsInGold() public view returns (uint256) {
    address stableTokenAddress = registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID);
    (uint256 numerator, uint256 denominator) = getSortedOracles().medianRate(stableTokenAddress);
    return
      numberValidatorsInCurrentSet().mul(targetValidatorEpochPayment).mul(denominator).div(
        numerator
      );
  }

  
  function _getTargetGoldSupplyIncrease() internal view returns (uint256) {
    uint256 targetEpochRewards = getTargetVoterRewards();
    uint256 targetTotalEpochPaymentsInGold = getTargetTotalEpochPaymentsInGold();
    uint256 targetGoldSupplyIncrease = targetEpochRewards.add(targetTotalEpochPaymentsInGold);
    
    targetGoldSupplyIncrease = FixidityLib
      .newFixed(targetGoldSupplyIncrease)
      .divide(
      FixidityLib.newFixed(1).subtract(communityRewardFraction).subtract(carbonOffsettingFraction)
    )
      .fromFixed();
    return targetGoldSupplyIncrease;
  }

  
  function getRewardsMultiplier() external view returns (uint256) {
    return _getRewardsMultiplier(_getTargetGoldSupplyIncrease()).unwrap();
  }

  
  function getVotingGoldFraction() public view returns (uint256) {
    uint256 liquidGold = getGoldToken().totalSupply().sub(getReserve().getReserveGoldBalance());
    uint256 votingGold = getElection().getTotalVotes();
    return FixidityLib.newFixed(votingGold).divide(FixidityLib.newFixed(liquidGold)).unwrap();
  }

  
  function _updateTargetVotingYield() internal onlyWhenNotFrozen {
    FixidityLib.Fraction memory votingGoldFraction = FixidityLib.wrap(getVotingGoldFraction());
    if (votingGoldFraction.gt(targetVotingGoldFraction)) {
      FixidityLib.Fraction memory votingGoldFractionDelta = votingGoldFraction.subtract(
        targetVotingGoldFraction
      );
      FixidityLib.Fraction memory targetVotingYieldDelta = votingGoldFractionDelta.multiply(
        targetVotingYieldParams.adjustmentFactor
      );
      if (targetVotingYieldDelta.gte(targetVotingYieldParams.target)) {
        targetVotingYieldParams.target = FixidityLib.newFixed(0);
      } else {
        targetVotingYieldParams.target = targetVotingYieldParams.target.subtract(
          targetVotingYieldDelta
        );
      }
    } else if (votingGoldFraction.lt(targetVotingGoldFraction)) {
      FixidityLib.Fraction memory votingGoldFractionDelta = targetVotingGoldFraction.subtract(
        votingGoldFraction
      );
      FixidityLib.Fraction memory targetVotingYieldDelta = votingGoldFractionDelta.multiply(
        targetVotingYieldParams.adjustmentFactor
      );
      targetVotingYieldParams.target = targetVotingYieldParams.target.add(targetVotingYieldDelta);
      if (targetVotingYieldParams.target.gt(targetVotingYieldParams.max)) {
        targetVotingYieldParams.target = targetVotingYieldParams.max;
      }
    }
    emit TargetVotingYieldUpdated(targetVotingYieldParams.target.unwrap());
  }

  
  function updateTargetVotingYield() external onlyVm onlyWhenNotFrozen {
    _updateTargetVotingYield();
  }

  
  function isReserveLow() external view returns (bool) {
    
    FixidityLib.Fraction memory timeSinceInitialization = FixidityLib.newFixed(now.sub(startTime));
    FixidityLib.Fraction memory m = FixidityLib.newFixed(25 * 365 * 1 days);
    FixidityLib.Fraction memory b = FixidityLib.newFixed(2);
    FixidityLib.Fraction memory criticalRatio;
    
    if (timeSinceInitialization.gte(m)) {
      criticalRatio = FixidityLib.fixed1();
    } else {
      criticalRatio = b.subtract(timeSinceInitialization.divide(m));
    }
    FixidityLib.Fraction memory ratio = FixidityLib.wrap(getReserve().getReserveRatio());
    return ratio.lte(criticalRatio);
  }

  
  function calculateTargetEpochRewards()
    external
    view
    onlyWhenNotFrozen
    returns (uint256, uint256, uint256, uint256)
  {
    uint256 targetVoterReward = getTargetVoterRewards();
    uint256 targetGoldSupplyIncrease = _getTargetGoldSupplyIncrease();
    FixidityLib.Fraction memory rewardsMultiplier = _getRewardsMultiplier(targetGoldSupplyIncrease);
    return (
      FixidityLib.newFixed(targetValidatorEpochPayment).multiply(rewardsMultiplier).fromFixed(),
      FixidityLib.newFixed(targetVoterReward).multiply(rewardsMultiplier).fromFixed(),
      FixidityLib
        .newFixed(targetGoldSupplyIncrease)
        .multiply(communityRewardFraction)
        .multiply(rewardsMultiplier)
        .fromFixed(),
      FixidityLib
        .newFixed(targetGoldSupplyIncrease)
        .multiply(carbonOffsettingFraction)
        .multiply(rewardsMultiplier)
        .fromFixed()
    );
  }
}
        

Contract ABI

[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getRewardsMultiplier","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"validatorSignerAddressFromCurrentSet","inputs":[{"type":"uint256","name":"index"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"initialized","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"getTargetVotingYieldParameters","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"carbonOffsettingPartner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"checkProofOfPossession","inputs":[{"type":"address","name":"sender"},{"type":"bytes","name":"blsKey"},{"type":"bytes","name":"blsPop"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getTargetVoterRewards","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochNumberOfBlock","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setCarbonOffsettingFund","inputs":[{"type":"address","name":"partner"},{"type":"uint256","name":"value"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getTargetTotalEpochPaymentsInGold","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"getVerifiedSealBitmapFromHeader","inputs":[{"type":"bytes","name":"header"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getTargetGoldTotalSupply","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setTargetVotingYieldParameters","inputs":[{"type":"uint256","name":"max"},{"type":"uint256","name":"adjustmentFactor"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"validatorSignerAddressFromSet","inputs":[{"type":"uint256","name":"index"},{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"getRewardsMultiplierParameters","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"calculateTargetEpochRewards","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"hashHeader","inputs":[{"type":"bytes","name":"header"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minQuorumSizeInCurrentSet","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"startTime","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"registry","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"registryAddress"},{"type":"uint256","name":"targetVotingYieldInitial"},{"type":"uint256","name":"targetVotingYieldMax"},{"type":"uint256","name":"targetVotingYieldAdjustmentFactor"},{"type":"uint256","name":"rewardsMultiplierMax"},{"type":"uint256","name":"rewardsMultiplierUnderspendAdjustmentFactor"},{"type":"uint256","name":"rewardsMultiplierOverspendAdjustmentFactor"},{"type":"uint256","name":"_targetVotingGoldFraction"},{"type":"uint256","name":"_targetValidatorEpochPayment"},{"type":"uint256","name":"_communityRewardFraction"},{"type":"address","name":"_carbonOffsettingPartner"},{"type":"uint256","name":"_carbonOffsettingFraction"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getCarbonOffsettingFraction","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setRewardsMultiplierParameters","inputs":[{"type":"uint256","name":"max"},{"type":"uint256","name":"underspendAdjustmentFactor"},{"type":"uint256","name":"overspendAdjustmentFactor"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"numberValidatorsInCurrentSet","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getBlockNumberFromHeader","inputs":[{"type":"bytes","name":"header"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"updateTargetVotingYield","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setTargetVotingGoldFraction","inputs":[{"type":"uint256","name":"value"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setTargetValidatorEpochPayment","inputs":[{"type":"uint256","name":"value"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getCommunityRewardFraction","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochNumber","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isReserveLow","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"numberValidatorsInSet","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getVotingGoldFraction","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRegistry","inputs":[{"type":"address","name":"registryAddress"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getTargetVotingGoldFraction","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setCommunityRewardFraction","inputs":[{"type":"uint256","name":"value"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"setTargetVotingYield","inputs":[{"type":"uint256","name":"targetVotingYield"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochSize","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"targetValidatorEpochPayment","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minQuorumSize","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"fractionMulExp","inputs":[{"type":"uint256","name":"aNumerator"},{"type":"uint256","name":"aDenominator"},{"type":"uint256","name":"bNumerator"},{"type":"uint256","name":"bDenominator"},{"type":"uint256","name":"exponent"},{"type":"uint256","name":"_decimals"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"getParentSealBitmap","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"event","name":"TargetVotingGoldFractionSet","inputs":[{"type":"uint256","name":"fraction","indexed":false}],"anonymous":false},{"type":"event","name":"CommunityRewardFractionSet","inputs":[{"type":"uint256","name":"fraction","indexed":false}],"anonymous":false},{"type":"event","name":"CarbonOffsettingFundSet","inputs":[{"type":"address","name":"partner","indexed":true},{"type":"uint256","name":"fraction","indexed":false}],"anonymous":false},{"type":"event","name":"TargetValidatorEpochPaymentSet","inputs":[{"type":"uint256","name":"payment","indexed":false}],"anonymous":false},{"type":"event","name":"TargetVotingYieldParametersSet","inputs":[{"type":"uint256","name":"max","indexed":false},{"type":"uint256","name":"adjustmentFactor","indexed":false}],"anonymous":false},{"type":"event","name":"TargetVotingYieldSet","inputs":[{"type":"uint256","name":"target","indexed":false}],"anonymous":false},{"type":"event","name":"RewardsMultiplierParametersSet","inputs":[{"type":"uint256","name":"max","indexed":false},{"type":"uint256","name":"underspendAdjustmentFactor","indexed":false},{"type":"uint256","name":"overspendAdjustmentFactor","indexed":false}],"anonymous":false},{"type":"event","name":"TargetVotingYieldUpdated","inputs":[{"type":"uint256","name":"fraction","indexed":false}],"anonymous":false},{"type":"event","name":"RegistrySet","inputs":[{"type":"address","name":"registryAddress","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":true},{"type":"address","name":"newOwner","indexed":true}],"anonymous":false}]
              

Contract Creation Code

0x6080604052600060025560006200001b620000bf60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350620000c7565b600033905090565b615d4180620000d76000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80638331c1d71161015c5780639b2b592f116100ce578063df4da46111610087578063df4da46114610e70578063e185aaa814610e8e578063e50e652d14610eac578063ec68307214610eee578063f2fde38b14610f69578063fae8db0a14610fad5761028a565b80639b2b592f14610d22578063a1b9596214610d64578063a91ee0dc14610d82578063ae098de214610dc6578063b63b4a2314610de4578063cd52782e14610e2a5761028a565b806392ecd7451161012057806392ecd74514610c2e5780639402838414610c3857806396c3d2fd14610c7e5780639917907f14610cc45780639a7b3be714610ce25780639ad0cce714610d005761028a565b80638331c1d714610a7b57806387ee8a0f14610ad55780638a88362614610af35780638da5cb5b14610bc25780638f32d59b14610c0c5761028a565b80635049890f11610200578063715018a6116101b9578063715018a6146109045780637385e5da1461090e57806378e979251461092c5780637b1039991461094a5780637cca2a3c146109945780637d16412514610a5d5761028a565b80635049890f146106f05780635918bb581461070e5780635d180adb1461075e5780635f396e48146107d6578063643470431461080257806367960e91146108355761028a565b806323f0ab651161025257806323f0ab65146103b35780632848f9e31461053d5780633b1eb4bf1461055b578063434c99c41461059d5780634901c725146106035780634b2c2f44146106215761028a565b80630203ab241461028f578063123633ea146102ad578063158ef93e1461031b578063171af90f1461033d57806322dae21f14610369575b600080fd5b610297610fef565b6040518082815260200191505060405180910390f35b6102d9600480360360208110156102c357600080fd5b810190808035906020019092919050505061100e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61032361115f565b604051808215151515815260200191505060405180910390f35b610345611172565b60405180848152602001838152602001828152602001935050505060405180910390f35b6103716111eb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610523600480360360608110156103c957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561040657600080fd5b82018360208201111561041857600080fd5b8035906020019184600183028401116401000000008311171561043a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561049d57600080fd5b8201836020820111156104af57600080fd5b803590602001918460018302840111640100000000831117156104d157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611211565b604051808215151515815260200191505060405180910390f35b6105456113ca565b6040518082815260200191505060405180910390f35b6105876004803603602081101561057157600080fd5b8101908080359060200190929190505050611494565b6040518082815260200191505060405180910390f35b6105e9600480360360408110156105b357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506114ae565b604051808215151515815260200191505060405180910390f35b61060b61167a565b6040518082815260200191505060405180910390f35b6106da6004803603602081101561063757600080fd5b810190808035906020019064010000000081111561065457600080fd5b82018360208201111561066657600080fd5b8035906020019184600183028401116401000000008311171561068857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061188a565b6040518082815260200191505060405180910390f35b6106f8611a1e565b6040518082815260200191505060405180910390f35b6107446004803603604081101561072457600080fd5b810190808035906020019092919080359060200190929190505050611b48565b604051808215151515815260200191505060405180910390f35b6107946004803603604081101561077457600080fd5b810190808035906020019092919080359060200190929190505050611d71565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107de611ec3565b60405180848152602001838152602001828152602001935050505060405180910390f35b61080a611f42565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b6108ee6004803603602081101561084b57600080fd5b810190808035906020019064010000000081111561086857600080fd5b82018360208201111561087a57600080fd5b8035906020019184600183028401116401000000008311171561089c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612177565b6040518082815260200191505060405180910390f35b61090c61230b565b005b610916612444565b6040518082815260200191505060405180910390f35b610934612454565b6040518082815260200191505060405180910390f35b61095261245a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a5b60048036036101808110156109ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612480565b005b610a6561258f565b6040518082815260200191505060405180910390f35b610abb60048036036060811015610a9157600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506125b5565b604051808215151515815260200191505060405180910390f35b610add6127eb565b6040518082815260200191505060405180910390f35b610bac60048036036020811015610b0957600080fd5b8101908080359060200190640100000000811115610b2657600080fd5b820183602082011115610b3857600080fd5b80359060200191846001830284011164010000000083111715610b5a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612932565b6040518082815260200191505060405180910390f35b610bca612ac6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c14612aef565b604051808215151515815260200191505060405180910390f35b610c36612b4d565b005b610c6460048036036020811015610c4e57600080fd5b8101908080359060200190929190505050612d0e565b604051808215151515815260200191505060405180910390f35b610caa60048036036020811015610c9457600080fd5b8101908080359060200190929190505050612ec0565b604051808215151515815260200191505060405180910390f35b610ccc612fde565b6040518082815260200191505060405180910390f35b610cea613004565b6040518082815260200191505060405180910390f35b610d08613014565b604051808215151515815260200191505060405180910390f35b610d4e60048036036020811015610d3857600080fd5b8101908080359060200190929190505050613176565b6040518082815260200191505060405180910390f35b610d6c6132bf565b6040518082815260200191505060405180910390f35b610dc460048036036020811015610d9857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134a3565b005b610dce613647565b6040518082815260200191505060405180910390f35b610e1060048036036020811015610dfa57600080fd5b810190808035906020019092919050505061366d565b604051808215151515815260200191505060405180910390f35b610e5660048036036020811015610e4057600080fd5b8101908080359060200190929190505050613786565b604051808215151515815260200191505060405180910390f35b610e786138ea565b6040518082815260200191505060405180910390f35b610e96613a26565b6040518082815260200191505060405180910390f35b610ed860048036036020811015610ec257600080fd5b8101908080359060200190929190505050613a2c565b6040518082815260200191505060405180910390f35b610f4c600480360360c0811015610f0457600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050613a77565b604051808381526020018281526020019250505060405180910390f35b610fab60048036036020811015610f7f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613c8b565b005b610fd960048036036020811015610fc357600080fd5b8101908080359060200190929190505050613d11565b6040518082815260200191505060405180910390f35b6000611009611004610fff613e5a565b613f11565b614216565b905090565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106110875780518252602082019150602081019050602083039250611064565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146110e7576040519150601f19603f3d011682016040523d82523d6000602084013e6110ec565b606091505b5080935081925050508061114b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180615b1d603d913960400191505060405180910390fd5b611156826000614224565b92505050919050565b600060149054906101000a900460ff1681565b6000806000806006905061119d81600001604051806020016040529081600082015481525050614216565b6111be82600201604051806020016040529081600082015481525050614216565b6111df83600101604051806020016040529081600082015481525050614216565b93509350935050909192565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b6020831061129a5780518252602082019150602081019050602083039250611277565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b602083106112eb57805182526020820191506020810190506020830392506112c8565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106113545780518252602082019150602081019050602083039250611331565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146113b4576040519150601f19603f3d011682016040523d82523d6000602084013e6113b9565b606091505b505080915050809150509392505050565b600061148f61148a600660000160405180602001604052908160008201548152505061147c6113f761423b565b73ffffffffffffffffffffffffffffffffffffffff16631f6042436040518163ffffffff1660e01b815260040160206040518083038186803b15801561143c57600080fd5b505afa158015611450573d6000803e3d6000fd5b505050506040513d602081101561146657600080fd5b8101908080519060200190929190505050614336565b6143c090919063ffffffff16565b61481f565b905090565b60006114a7826114a26138ea565b614840565b9050919050565b60006114b8612aef565b61152a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415806115a557506115a1600b604051806020016040529081600082015481525050614216565b8214155b6115ae57600080fd5b6115be6115b9614878565b614216565b82106115c957600080fd5b82600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506116138261489e565b600b600082015181600001559050508273ffffffffffffffffffffffffffffffffffffffff167fe296227209b47bb8f4a76768ebd564dcde1c44be325a5d262f27c1fd4fd4538b836040518082815260200191505060405180910390a26001905092915050565b600080600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f537461626c65546f6b656e000000000000000000000000000000000000000000815250600b019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561173657600080fd5b505afa15801561174a573d6000803e3d6000fd5b505050506040513d602081101561176057600080fd5b8101908080519060200190929190505050905060008061177e6148bc565b73ffffffffffffffffffffffffffffffffffffffff1663ef90e1b0846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050604080518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d604081101561182357600080fd5b810190808051906020019092919080519060200190929190505050915091506118828261187483611866600d546118586127eb565b6149b790919063ffffffff16565b6149b790919063ffffffff16565b614a3d90919063ffffffff16565b935050505090565b60006060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106118df57805182526020820191506020810190506020830392506118bc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106119465780518252602082019150602081019050602083039250611923565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146119a6576040519150601f19603f3d011682016040523d82523d6000602084013e6119ab565b606091505b50809350819250505080611a0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180615a6b6038913960400191505060405180910390fd5b611a15826000614a87565b92505050919050565b600080611a3660025442614b1890919063ffffffff16565b90506201518061016d600f0202811015611ae8576000611a8a6002611a7c6b01f04ef12cb04cf1580000006b033b2e3c9fd0803ce8000000614b1890919063ffffffff16565b614a3d90919063ffffffff16565b90506000611abd6201518061016d600f0202611aaf85856149b790919063ffffffff16565b614a3d90919063ffffffff16565b9050611ade6b01f04ef12cb04cf15800000082614b6290919063ffffffff16565b9350505050611b45565b6000611b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615a396032913960400191505060405180910390fd5b60009150505b90565b6000611b52612aef565b611bc4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611be66006600201604051806020016040529081600082015481525050614216565b83141580611c155750611c116006600101604051806020016040529081600082015481525050614216565b8214155b611c6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615afb6022913960400191505060405180910390fd5b611c738361489e565b600660020160008201518160000155905050611c8e8261489e565b600660010160008201518160000155905050611cd3611cab614878565b6006600201604051806020016040529081600082015481525050614bea90919063ffffffff16565b611d28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615cc4602f913960400191505060405180910390fd5b7f1b76e38f3fdd1f284ed4d47c9d50ff407748c516ff9761616ff638c2331076258383604051808381526020018281526020019250505060405180910390a16001905092915050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310611dea5780518252602082019150602081019050602083039250611dc7565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611e4a576040519150601f19603f3d011682016040523d82523d6000602084013e611e4f565b606091505b50809350819250505080611eae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180615bc46036913960400191505060405180910390fd5b611eb9826000614224565b9250505092915050565b60008060008060039050611eee81600201604051806020016040529081600082015481525050614216565b611f1282600001600001604051806020016040529081600082015481525050614216565b611f3683600001600101604051806020016040529081600082015481525050614216565b93509350935050909192565b600080600080611f50614bff565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611fcc57600080fd5b505afa158015611fe0573d6000803e3d6000fd5b505050506040513d6020811015611ff657600080fd5b81019080805190602001909291905050501561205d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615aa36022913960400191505060405180910390fd5b60006120676113ca565b90506000612073613e5a565b905061207d615930565b61208682613f11565b90506120ad6120a88261209a600d54614336565b6143c090919063ffffffff16565b61481f565b6120d06120cb836120bd87614336565b6143c090919063ffffffff16565b61481f565b61211b61211684612108600a6040518060200160405290816000820154815250506120fa89614336565b6143c090919063ffffffff16565b6143c090919063ffffffff16565b61481f565b61216661216185612153600b6040518060200160405290816000820154815250506121458a614336565b6143c090919063ffffffff16565b6143c090919063ffffffff16565b61481f565b965096509650965050505090919293565b60006060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106121cc57805182526020820191506020810190506020830392506121a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106122335780518252602082019150602081019050602083039250612210565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612293576040519150601f19603f3d011682016040523d82523d6000602084013e612298565b606091505b508093508192505050806122f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615cf36023913960400191505060405180910390fd5b612302826000614a87565b92505050919050565b612313612aef565b612385576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600061244f43613a2c565b905090565b60025481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1615612503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555061252733614cfa565b6125308c6134a3565b61253a8a8a611b48565b506125468888886125b5565b5061255085612d0e565b5061255a84612ec0565b506125648361366d565b5061256f82826114ae565b506125798b613786565b5042600281905550505050505050505050505050565b60006125b0600b604051806020016040529081600082015481525050614216565b905090565b60006125bf612aef565b612631576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6126536003600201604051806020016040529081600082015481525050614216565b8414158061268557506126816003600001600101604051806020016040529081600082015481525050614216565b8214155b806126b457506126b06003600001600001604051806020016040529081600082015481525050614216565b8314155b612709576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061599a6021913960400191505060405180910390fd5b604051806040016040528060405180604001604052806127288761489e565b81526020016127368661489e565b81525081526020016127478661489e565b815250600360008201518160000160008201518160000160008201518160000155505060208201518160010160008201518160000155505050506020820151816002016000820151816000015550509050507f191445ee0115396c9725b9c642b985d63820ca57d54e42e5eb38faec4022f05d84848460405180848152602001838152602001828152602001935050505060405180910390a1600190509392505050565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061285c5780518252602082019150602081019050602083039250612839565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146128bc576040519150601f19603f3d011682016040523d82523d6000602084013e6128c1565b606091505b50809350819250505080612920576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180615b5a6035913960400191505060405180910390fd5b61292b826000614224565b9250505090565b60006060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106129875780518252602082019150602081019050602083039250612964565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106129ee57805182526020820191506020810190506020830392506129cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612a4e576040519150601f19603f3d011682016040523d82523d6000602084013e612a53565b606091505b50809350819250505080612ab2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180615c936031913960400191505060405180910390fd5b612abd826000614224565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b31614e3e565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612bef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4f6e6c7920564d2063616e2063616c6c0000000000000000000000000000000081525060200191505060405180910390fd5b612bf7614bff565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612c7357600080fd5b505afa158015612c87573d6000803e3d6000fd5b505050506040513d6020811015612c9d57600080fd5b810190808051906020019092919050505015612d04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615aa36022913960400191505060405180910390fd5b612d0c614e46565b565b6000612d18612aef565b612d8a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612da96009604051806020016040529081600082015481525050614216565b821415612e01576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806159bb6025913960400191505060405180910390fd5b612e11612e0c614878565b614216565b8210612e68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526033815260200180615a066033913960400191505060405180910390fd5b612e718261489e565b6009600082015181600001559050507fbae2f33c70949fbc7325c98655f3039e5e1c7f774874c99fd4f31ec5f432b159826040518082815260200191505060405180910390a160019050919050565b6000612eca612aef565b612f3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600d54821415612f97576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806159446028913960400191505060405180910390fd5b81600d819055507fa21d141963bb2c1064b5376f762d22d3e9c4c51617edcf105bcec0f14e36800c826040518082815260200191505060405180910390a160019050919050565b6000612fff600a604051806020016040529081600082015481525050614216565b905090565b600061300f43611494565b905090565b600061301e615930565b61303b61303660025442614b1890919063ffffffff16565b614336565b9050613045615930565b613052632efe0780614336565b905061305c615930565b6130666002614336565b9050613070615930565b613083838561523a90919063ffffffff16565b1561309757613090614878565b90506130bf565b6130bc6130ad848661525090919063ffffffff16565b8361539990919063ffffffff16565b90505b6130c7615930565b6131576130d2615440565b73ffffffffffffffffffffffffffffffffffffffff166356b6d0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561311757600080fd5b505afa15801561312b573d6000803e3d6000fd5b505050506040513d602081101561314157600080fd5b810190808051906020019092919050505061489e565b905061316c828261553b90919063ffffffff16565b9550505050505090565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106131e757805182526020820191506020810190506020830392506131c4565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613247576040519150601f19603f3d011682016040523d82523d6000602084013e61324c565b606091505b508093508192505050806132ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061596c602e913960400191505060405180910390fd5b6132b6826000614224565b92505050919050565b6000806133e36132cd615440565b73ffffffffffffffffffffffffffffffffffffffff16638d9a5e6f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561331257600080fd5b505afa158015613326573d6000803e3d6000fd5b505050506040513d602081101561333c57600080fd5b8101908080519060200190929190505050613355615551565b73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561339a57600080fd5b505afa1580156133ae573d6000803e3d6000fd5b505050506040513d60208110156133c457600080fd5b8101908080519060200190929190505050614b1890919063ffffffff16565b905060006133ef61423b565b73ffffffffffffffffffffffffffffffffffffffff16639a0e7d666040518163ffffffff1660e01b815260040160206040518083038186803b15801561343457600080fd5b505afa158015613448573d6000803e3d6000fd5b505050506040513d602081101561345e57600080fd5b8101908080519060200190929190505050905061349c61349761348084614336565b61348984614336565b61525090919063ffffffff16565b614216565b9250505090565b6134ab612aef565b61351d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156135c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b60006136686009604051806020016040529081600082015481525050614216565b905090565b6000613677612aef565b6136e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613708600a604051806020016040529081600082015481525050614216565b8214158015613725575061372261371d614878565b614216565b82105b61372e57600080fd5b6137378261489e565b600a600082015181600001559050507fe6c1b64ad7e601924731051286b7b408b1a6f3ae96dcd6d2d9cd82578372ef9e826040518082815260200191505060405180910390a160019050919050565b6000613790612aef565b613802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61380a615930565b6138138361489e565b905061384160066002016040518060200160405290816000820154815250508261553b90919063ffffffff16565b613896576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180615b8f6035913960400191505060405180910390fd5b806006600001600082015181600001559050507f152c3fc1e1cd415804bc9ae15876b37e62d8909358b940e6f4847ca927f46637836040518082815260200191505060405180910390a16001915050919050565b60006060600060f873ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040518082805190602001908083835b60208310613950578051825260208201915060208101905060208303925061392d565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146139b0576040519150601f19603f3d011682016040523d82523d6000602084013e6139b5565b606091505b50809350819250505080613a14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615c426025913960400191505060405180910390fd5b613a1f826000614224565b9250505090565b600d5481565b6000613a706003613a626002613a546002613a4688613176565b6149b790919063ffffffff16565b614b6290919063ffffffff16565b614a3d90919063ffffffff16565b9050919050565b60008060008714158015613a8c575060008514155b613afe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310613b985780518252602082019150602081019050602083039250613b75565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613bf8576040519150601f19603f3d011682016040523d82523d6000602084013e613bfd565b606091505b50809250819350505081613c5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180615c1b6027913960400191505060405180910390fd5b613c67816000614224565b9350613c74816020614224565b925083839550955050505050965096945050505050565b613c93612aef565b613d05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613d0e81614cfa565b50565b60006060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310613d825780518252602082019150602081019050602083039250613d5f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613de2576040519150601f19603f3d011682016040523d82523d6000602084013e613de7565b606091505b50809350819250505080613e46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615c67602c913960400191505060405180910390fd5b613e51826000614a87565b92505050919050565b600080613e656113ca565b90506000613e7161167a565b90506000613e888284614b6290919063ffffffff16565b9050613f06613f01613eea600b604051806020016040529081600082015481525050613edc600a604051806020016040529081600082015481525050613ece6001614336565b61539990919063ffffffff16565b61539990919063ffffffff16565b613ef384614336565b61525090919063ffffffff16565b61481f565b905080935050505090565b613f19615930565b6000613f23611a1e565b90506000613f2f615551565b73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f7457600080fd5b505afa158015613f88573d6000803e3d6000fd5b505050506040513d6020811015613f9e57600080fd5b810190808051906020019092919050505090506000613fe4613fc98684614b6290919063ffffffff16565b6b033b2e3c9fd0803ce8000000614b1890919063ffffffff16565b90506000614007846b033b2e3c9fd0803ce8000000614b1890919063ffffffff16565b9050614011615930565b61403461401d83614336565b61402685614336565b61525090919063ffffffff16565b9050614050614041614878565b8261564c90919063ffffffff16565b156141335761405d615930565b6140a56003600001600001604051806020016040529081600082015481525050614097614088614878565b8561539990919063ffffffff16565b6143c090919063ffffffff16565b90506140af615930565b6140c9826140bb614878565b61566190919063ffffffff16565b90506140f7600360020160405180602001604052908160008201548152505082614bea90919063ffffffff16565b1561410b5780975050505050505050614211565b6003600201604051806020016040529081600082015481525050975050505050505050614211565b61414d61413e614878565b82614bea90919063ffffffff16565b156142015761415a615930565b6141a2600360000160010160405180602001604052908160008201548152505061419484614186614878565b61539990919063ffffffff16565b6143c090919063ffffffff16565b90506141be6141af614878565b82614bea90919063ffffffff16565b156141ea576141dd816141cf614878565b61539990919063ffffffff16565b9650505050505050614211565b6141f4600061489e565b9650505050505050614211565b614209614878565b955050505050505b919050565b600081600001519050919050565b60006142308383614a87565b60001c905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f456c656374696f6e0000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156142f657600080fd5b505afa15801561430a573d6000803e3d6000fd5b505050506040513d602081101561432057600080fd5b8101908080519060200190929190505050905090565b61433e615930565b61434661570a565b82111561439e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180615ac56036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b6143c8615930565b6000836000015114806143df575060008260000151145b156143fb57604051806020016040528060008152509050614819565b69d3c21bcecceda10000008260000151141561441957829050614819565b69d3c21bcecceda10000008360000151141561443757819050614819565b600069d3c21bcecceda100000061444d85615729565b600001518161445857fe5b049050600061446685615760565b600001519050600069d3c21bcecceda100000061448286615729565b600001518161448d57fe5b049050600061449b86615760565b600001519050600082850290506000851461452f57828582816144ba57fe5b041461452e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda100000082029050600082146145d15769d3c21bcecceda100000082828161455c57fe5b04146145d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b809150600084860290506000861461466257848682816145ed57fe5b0414614661576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b60008488029050600088146146f0578488828161467b57fe5b04146146ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b6146f861579d565b878161470057fe5b04965061470b61579d565b858161471357fe5b04945060008588029050600088146147a4578588828161472f57fe5b04146147a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b6147ac615930565b60405180602001604052808781525090506147d581604051806020016040528087815250615661565b90506147ef81604051806020016040528086815250615661565b905061480981604051806020016040528085815250615661565b9050809a50505050505050505050505b92915050565b600069d3c21bcecceda100000082600001518161483857fe5b049050919050565b60008082848161484c57fe5b049050600083858161485a57fe5b06141561486a5780915050614872565b600181019150505b92915050565b614880615930565b604051806020016040528069d3c21bcecceda1000000815250905090565b6148a6615930565b6040518060200160405280838152509050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f536f727465644f7261636c657300000000000000000000000000000000000000815250600d019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561497757600080fd5b505afa15801561498b573d6000803e3d6000fd5b505050506040513d60208110156149a157600080fd5b8101908080519060200190929190505050905090565b6000808314156149ca5760009050614a37565b60008284029050828482816149db57fe5b0414614a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615bfa6021913960400191505060405180910390fd5b809150505b92915050565b6000614a7f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506157aa565b905092915050565b60006020820183511015614b03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b6000614b5a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615870565b905092915050565b600080828401905083811015614be0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60008160000151836000015110905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f467265657a6572000000000000000000000000000000000000000000000000008152506007019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614cba57600080fd5b505afa158015614cce573d6000803e3d6000fd5b505050506040513d6020811015614ce457600080fd5b8101908080519060200190929190505050905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614d80576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806159e06026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b614e4e614bff565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015614eca57600080fd5b505afa158015614ede573d6000803e3d6000fd5b505050506040513d6020811015614ef457600080fd5b810190808051906020019092919050505015614f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615aa36022913960400191505060405180910390fd5b614f63615930565b614f73614f6e6132bf565b61489e565b9050614f9e60096040518060200160405290816000820154815250508261564c90919063ffffffff16565b156150a457614fab615930565b614fd460096040518060200160405290816000820154815250508361539990919063ffffffff16565b9050614fde615930565b61500a6006600101604051806020016040529081600082015481525050836143c090919063ffffffff16565b905061503860066000016040518060200160405290816000820154815250508261523a90919063ffffffff16565b1561505e576150476000614336565b60066000016000820151816000015590505061509d565b61508a81600660000160405180602001604052908160008201548152505061539990919063ffffffff16565b6006600001600082015181600001559050505b50506151df565b6150cd600960405180602001604052908160008201548152505082614bea90919063ffffffff16565b156151de576150da615930565b61510382600960405180602001604052908160008201548152505061539990919063ffffffff16565b905061510d615930565b6151396006600101604051806020016040529081600082015481525050836143c090919063ffffffff16565b905061516781600660000160405180602001604052908160008201548152505061566190919063ffffffff16565b6006600001600082015181600001559050506151be6006600201604051806020016040529081600082015481525050600660000160405180602001604052908160008201548152505061564c90919063ffffffff16565b156151db5760066002016006600001600082015481600001559050505b50505b5b7f49d8cdfe05bae61517c234f65f4088454013bafe561115126a8fe0074dc7700e6152226006600001604051806020016040529081600082015481525050614216565b6040518082815260200191505060405180910390a150565b6000816000015183600001511015905092915050565b615258615930565b6000826000015114156152d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f63616e277420646976696465206279203000000000000000000000000000000081525060200191505060405180910390fd5b600069d3c21bcecceda10000008460000151029050836000015169d3c21bcecceda1000000828161530057fe5b0414615374576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6f766572666c6f7720617420646976696465000000000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808460000151838161538c57fe5b0481525091505092915050565b6153a1615930565b81600001518360000151101561541f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f737562737472616374696f6e20756e646572666c6f772064657465637465640081525060200191505060405180910390fd5b60405180602001604052808360000151856000015103815250905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f52657365727665000000000000000000000000000000000000000000000000008152506007019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156154fb57600080fd5b505afa15801561550f573d6000803e3d6000fd5b505050506040513d602081101561552557600080fd5b8101908080519060200190929190505050905090565b6000816000015183600001511115905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561560c57600080fd5b505afa158015615620573d6000803e3d6000fd5b505050506040513d602081101561563657600080fd5b8101908080519060200190929190505050905090565b60008160000151836000015111905092915050565b615669615930565b60008260000151846000015101905083600001518110156156f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b615731615930565b604051806020016040528069d3c21bcecceda10000008085600001518161575457fe5b04028152509050919050565b615768615930565b604051806020016040528069d3c21bcecceda10000008085600001518161578b57fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b60008083118290615856576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561581b578082015181840152602081019050615800565b50505050905090810190601f1680156158485780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161586257fe5b049050809150509392505050565b600083831115829061591d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158e25780820151818401526020810190506158c7565b50505050905090810190601f16801561590f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b604051806020016040528060008152509056fe5461726765742076616c696461746f722065706f6368207061796d656e7420756e6368616e6765646572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c654261642072657761726473206d756c7469706c69657220706172616d657465727354617267657420766f74696e6720676f6c64206672616374696f6e20756e6368616e6765644f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737354617267657420766f74696e6720676f6c64206672616374696f6e2063616e6e6f74206265206c6172676572207468616e2031496d706c656d656e7420626c6f636b207265776172642063616c63756c6174696f6e20666f722079656172732031352d33306572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c6563616e27742063616c6c207768656e20636f6e74726163742069732066726f7a656e63616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e6577466978656428294261642074617267657420766f74696e67207969656c6420706172616d65746572736572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c6554617267657420766f74696e67207969656c64206d757374206265206c657373207468616e206f7220657175616c20746f206d61786572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c656572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c656572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c654d61782074617267657420766f74696e67207969656c64206d757374206265206c6f776572207468616e20313030256572726f722063616c6c696e67206861736848656164657220707265636f6d70696c65a165627a7a72305820130af7e533b5b625073d2c0191e3d00625ce0200ffe3e2e786e7b1a207eb20f20029

Deployed ByteCode

0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80638331c1d71161015c5780639b2b592f116100ce578063df4da46111610087578063df4da46114610e70578063e185aaa814610e8e578063e50e652d14610eac578063ec68307214610eee578063f2fde38b14610f69578063fae8db0a14610fad5761028a565b80639b2b592f14610d22578063a1b9596214610d64578063a91ee0dc14610d82578063ae098de214610dc6578063b63b4a2314610de4578063cd52782e14610e2a5761028a565b806392ecd7451161012057806392ecd74514610c2e5780639402838414610c3857806396c3d2fd14610c7e5780639917907f14610cc45780639a7b3be714610ce25780639ad0cce714610d005761028a565b80638331c1d714610a7b57806387ee8a0f14610ad55780638a88362614610af35780638da5cb5b14610bc25780638f32d59b14610c0c5761028a565b80635049890f11610200578063715018a6116101b9578063715018a6146109045780637385e5da1461090e57806378e979251461092c5780637b1039991461094a5780637cca2a3c146109945780637d16412514610a5d5761028a565b80635049890f146106f05780635918bb581461070e5780635d180adb1461075e5780635f396e48146107d6578063643470431461080257806367960e91146108355761028a565b806323f0ab651161025257806323f0ab65146103b35780632848f9e31461053d5780633b1eb4bf1461055b578063434c99c41461059d5780634901c725146106035780634b2c2f44146106215761028a565b80630203ab241461028f578063123633ea146102ad578063158ef93e1461031b578063171af90f1461033d57806322dae21f14610369575b600080fd5b610297610fef565b6040518082815260200191505060405180910390f35b6102d9600480360360208110156102c357600080fd5b810190808035906020019092919050505061100e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61032361115f565b604051808215151515815260200191505060405180910390f35b610345611172565b60405180848152602001838152602001828152602001935050505060405180910390f35b6103716111eb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610523600480360360608110156103c957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561040657600080fd5b82018360208201111561041857600080fd5b8035906020019184600183028401116401000000008311171561043a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561049d57600080fd5b8201836020820111156104af57600080fd5b803590602001918460018302840111640100000000831117156104d157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611211565b604051808215151515815260200191505060405180910390f35b6105456113ca565b6040518082815260200191505060405180910390f35b6105876004803603602081101561057157600080fd5b8101908080359060200190929190505050611494565b6040518082815260200191505060405180910390f35b6105e9600480360360408110156105b357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506114ae565b604051808215151515815260200191505060405180910390f35b61060b61167a565b6040518082815260200191505060405180910390f35b6106da6004803603602081101561063757600080fd5b810190808035906020019064010000000081111561065457600080fd5b82018360208201111561066657600080fd5b8035906020019184600183028401116401000000008311171561068857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061188a565b6040518082815260200191505060405180910390f35b6106f8611a1e565b6040518082815260200191505060405180910390f35b6107446004803603604081101561072457600080fd5b810190808035906020019092919080359060200190929190505050611b48565b604051808215151515815260200191505060405180910390f35b6107946004803603604081101561077457600080fd5b810190808035906020019092919080359060200190929190505050611d71565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107de611ec3565b60405180848152602001838152602001828152602001935050505060405180910390f35b61080a611f42565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b6108ee6004803603602081101561084b57600080fd5b810190808035906020019064010000000081111561086857600080fd5b82018360208201111561087a57600080fd5b8035906020019184600183028401116401000000008311171561089c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612177565b6040518082815260200191505060405180910390f35b61090c61230b565b005b610916612444565b6040518082815260200191505060405180910390f35b610934612454565b6040518082815260200191505060405180910390f35b61095261245a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a5b60048036036101808110156109ab57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612480565b005b610a6561258f565b6040518082815260200191505060405180910390f35b610abb60048036036060811015610a9157600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506125b5565b604051808215151515815260200191505060405180910390f35b610add6127eb565b6040518082815260200191505060405180910390f35b610bac60048036036020811015610b0957600080fd5b8101908080359060200190640100000000811115610b2657600080fd5b820183602082011115610b3857600080fd5b80359060200191846001830284011164010000000083111715610b5a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612932565b6040518082815260200191505060405180910390f35b610bca612ac6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c14612aef565b604051808215151515815260200191505060405180910390f35b610c36612b4d565b005b610c6460048036036020811015610c4e57600080fd5b8101908080359060200190929190505050612d0e565b604051808215151515815260200191505060405180910390f35b610caa60048036036020811015610c9457600080fd5b8101908080359060200190929190505050612ec0565b604051808215151515815260200191505060405180910390f35b610ccc612fde565b6040518082815260200191505060405180910390f35b610cea613004565b6040518082815260200191505060405180910390f35b610d08613014565b604051808215151515815260200191505060405180910390f35b610d4e60048036036020811015610d3857600080fd5b8101908080359060200190929190505050613176565b6040518082815260200191505060405180910390f35b610d6c6132bf565b6040518082815260200191505060405180910390f35b610dc460048036036020811015610d9857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506134a3565b005b610dce613647565b6040518082815260200191505060405180910390f35b610e1060048036036020811015610dfa57600080fd5b810190808035906020019092919050505061366d565b604051808215151515815260200191505060405180910390f35b610e5660048036036020811015610e4057600080fd5b8101908080359060200190929190505050613786565b604051808215151515815260200191505060405180910390f35b610e786138ea565b6040518082815260200191505060405180910390f35b610e96613a26565b6040518082815260200191505060405180910390f35b610ed860048036036020811015610ec257600080fd5b8101908080359060200190929190505050613a2c565b6040518082815260200191505060405180910390f35b610f4c600480360360c0811015610f0457600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050613a77565b604051808381526020018281526020019250505060405180910390f35b610fab60048036036020811015610f7f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613c8b565b005b610fd960048036036020811015610fc357600080fd5b8101908080359060200190929190505050613d11565b6040518082815260200191505060405180910390f35b6000611009611004610fff613e5a565b613f11565b614216565b905090565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106110875780518252602082019150602081019050602083039250611064565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146110e7576040519150601f19603f3d011682016040523d82523d6000602084013e6110ec565b606091505b5080935081925050508061114b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180615b1d603d913960400191505060405180910390fd5b611156826000614224565b92505050919050565b600060149054906101000a900460ff1681565b6000806000806006905061119d81600001604051806020016040529081600082015481525050614216565b6111be82600201604051806020016040529081600082015481525050614216565b6111df83600101604051806020016040529081600082015481525050614216565b93509350935050909192565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b6020831061129a5780518252602082019150602081019050602083039250611277565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b602083106112eb57805182526020820191506020810190506020830392506112c8565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b602083106113545780518252602082019150602081019050602083039250611331565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146113b4576040519150601f19603f3d011682016040523d82523d6000602084013e6113b9565b606091505b505080915050809150509392505050565b600061148f61148a600660000160405180602001604052908160008201548152505061147c6113f761423b565b73ffffffffffffffffffffffffffffffffffffffff16631f6042436040518163ffffffff1660e01b815260040160206040518083038186803b15801561143c57600080fd5b505afa158015611450573d6000803e3d6000fd5b505050506040513d602081101561146657600080fd5b8101908080519060200190929190505050614336565b6143c090919063ffffffff16565b61481f565b905090565b60006114a7826114a26138ea565b614840565b9050919050565b60006114b8612aef565b61152a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415806115a557506115a1600b604051806020016040529081600082015481525050614216565b8214155b6115ae57600080fd5b6115be6115b9614878565b614216565b82106115c957600080fd5b82600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506116138261489e565b600b600082015181600001559050508273ffffffffffffffffffffffffffffffffffffffff167fe296227209b47bb8f4a76768ebd564dcde1c44be325a5d262f27c1fd4fd4538b836040518082815260200191505060405180910390a26001905092915050565b600080600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f537461626c65546f6b656e000000000000000000000000000000000000000000815250600b019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561173657600080fd5b505afa15801561174a573d6000803e3d6000fd5b505050506040513d602081101561176057600080fd5b8101908080519060200190929190505050905060008061177e6148bc565b73ffffffffffffffffffffffffffffffffffffffff1663ef90e1b0846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001915050604080518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d604081101561182357600080fd5b810190808051906020019092919080519060200190929190505050915091506118828261187483611866600d546118586127eb565b6149b790919063ffffffff16565b6149b790919063ffffffff16565b614a3d90919063ffffffff16565b935050505090565b60006060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106118df57805182526020820191506020810190506020830392506118bc565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106119465780518252602082019150602081019050602083039250611923565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146119a6576040519150601f19603f3d011682016040523d82523d6000602084013e6119ab565b606091505b50809350819250505080611a0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180615a6b6038913960400191505060405180910390fd5b611a15826000614a87565b92505050919050565b600080611a3660025442614b1890919063ffffffff16565b90506201518061016d600f0202811015611ae8576000611a8a6002611a7c6b01f04ef12cb04cf1580000006b033b2e3c9fd0803ce8000000614b1890919063ffffffff16565b614a3d90919063ffffffff16565b90506000611abd6201518061016d600f0202611aaf85856149b790919063ffffffff16565b614a3d90919063ffffffff16565b9050611ade6b01f04ef12cb04cf15800000082614b6290919063ffffffff16565b9350505050611b45565b6000611b3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615a396032913960400191505060405180910390fd5b60009150505b90565b6000611b52612aef565b611bc4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611be66006600201604051806020016040529081600082015481525050614216565b83141580611c155750611c116006600101604051806020016040529081600082015481525050614216565b8214155b611c6a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615afb6022913960400191505060405180910390fd5b611c738361489e565b600660020160008201518160000155905050611c8e8261489e565b600660010160008201518160000155905050611cd3611cab614878565b6006600201604051806020016040529081600082015481525050614bea90919063ffffffff16565b611d28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615cc4602f913960400191505060405180910390fd5b7f1b76e38f3fdd1f284ed4d47c9d50ff407748c516ff9761616ff638c2331076258383604051808381526020018281526020019250505060405180910390a16001905092915050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310611dea5780518252602082019150602081019050602083039250611dc7565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611e4a576040519150601f19603f3d011682016040523d82523d6000602084013e611e4f565b606091505b50809350819250505080611eae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180615bc46036913960400191505060405180910390fd5b611eb9826000614224565b9250505092915050565b60008060008060039050611eee81600201604051806020016040529081600082015481525050614216565b611f1282600001600001604051806020016040529081600082015481525050614216565b611f3683600001600101604051806020016040529081600082015481525050614216565b93509350935050909192565b600080600080611f50614bff565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611fcc57600080fd5b505afa158015611fe0573d6000803e3d6000fd5b505050506040513d6020811015611ff657600080fd5b81019080805190602001909291905050501561205d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615aa36022913960400191505060405180910390fd5b60006120676113ca565b90506000612073613e5a565b905061207d615930565b61208682613f11565b90506120ad6120a88261209a600d54614336565b6143c090919063ffffffff16565b61481f565b6120d06120cb836120bd87614336565b6143c090919063ffffffff16565b61481f565b61211b61211684612108600a6040518060200160405290816000820154815250506120fa89614336565b6143c090919063ffffffff16565b6143c090919063ffffffff16565b61481f565b61216661216185612153600b6040518060200160405290816000820154815250506121458a614336565b6143c090919063ffffffff16565b6143c090919063ffffffff16565b61481f565b965096509650965050505090919293565b60006060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106121cc57805182526020820191506020810190506020830392506121a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106122335780518252602082019150602081019050602083039250612210565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612293576040519150601f19603f3d011682016040523d82523d6000602084013e612298565b606091505b508093508192505050806122f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615cf36023913960400191505060405180910390fd5b612302826000614a87565b92505050919050565b612313612aef565b612385576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600061244f43613a2c565b905090565b60025481565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1615612503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555061252733614cfa565b6125308c6134a3565b61253a8a8a611b48565b506125468888886125b5565b5061255085612d0e565b5061255a84612ec0565b506125648361366d565b5061256f82826114ae565b506125798b613786565b5042600281905550505050505050505050505050565b60006125b0600b604051806020016040529081600082015481525050614216565b905090565b60006125bf612aef565b612631576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6126536003600201604051806020016040529081600082015481525050614216565b8414158061268557506126816003600001600101604051806020016040529081600082015481525050614216565b8214155b806126b457506126b06003600001600001604051806020016040529081600082015481525050614216565b8314155b612709576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061599a6021913960400191505060405180910390fd5b604051806040016040528060405180604001604052806127288761489e565b81526020016127368661489e565b81525081526020016127478661489e565b815250600360008201518160000160008201518160000160008201518160000155505060208201518160010160008201518160000155505050506020820151816002016000820151816000015550509050507f191445ee0115396c9725b9c642b985d63820ca57d54e42e5eb38faec4022f05d84848460405180848152602001838152602001828152602001935050505060405180910390a1600190509392505050565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061285c5780518252602082019150602081019050602083039250612839565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146128bc576040519150601f19603f3d011682016040523d82523d6000602084013e6128c1565b606091505b50809350819250505080612920576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180615b5a6035913960400191505060405180910390fd5b61292b826000614224565b9250505090565b60006060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106129875780518252602082019150602081019050602083039250612964565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b602083106129ee57805182526020820191506020810190506020830392506129cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612a4e576040519150601f19603f3d011682016040523d82523d6000602084013e612a53565b606091505b50809350819250505080612ab2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180615c936031913960400191505060405180910390fd5b612abd826000614224565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612b31614e3e565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612bef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f4f6e6c7920564d2063616e2063616c6c0000000000000000000000000000000081525060200191505060405180910390fd5b612bf7614bff565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612c7357600080fd5b505afa158015612c87573d6000803e3d6000fd5b505050506040513d6020811015612c9d57600080fd5b810190808051906020019092919050505015612d04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615aa36022913960400191505060405180910390fd5b612d0c614e46565b565b6000612d18612aef565b612d8a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612da96009604051806020016040529081600082015481525050614216565b821415612e01576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806159bb6025913960400191505060405180910390fd5b612e11612e0c614878565b614216565b8210612e68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526033815260200180615a066033913960400191505060405180910390fd5b612e718261489e565b6009600082015181600001559050507fbae2f33c70949fbc7325c98655f3039e5e1c7f774874c99fd4f31ec5f432b159826040518082815260200191505060405180910390a160019050919050565b6000612eca612aef565b612f3c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600d54821415612f97576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806159446028913960400191505060405180910390fd5b81600d819055507fa21d141963bb2c1064b5376f762d22d3e9c4c51617edcf105bcec0f14e36800c826040518082815260200191505060405180910390a160019050919050565b6000612fff600a604051806020016040529081600082015481525050614216565b905090565b600061300f43611494565b905090565b600061301e615930565b61303b61303660025442614b1890919063ffffffff16565b614336565b9050613045615930565b613052632efe0780614336565b905061305c615930565b6130666002614336565b9050613070615930565b613083838561523a90919063ffffffff16565b1561309757613090614878565b90506130bf565b6130bc6130ad848661525090919063ffffffff16565b8361539990919063ffffffff16565b90505b6130c7615930565b6131576130d2615440565b73ffffffffffffffffffffffffffffffffffffffff166356b6d0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801561311757600080fd5b505afa15801561312b573d6000803e3d6000fd5b505050506040513d602081101561314157600080fd5b810190808051906020019092919050505061489e565b905061316c828261553b90919063ffffffff16565b9550505050505090565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106131e757805182526020820191506020810190506020830392506131c4565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613247576040519150601f19603f3d011682016040523d82523d6000602084013e61324c565b606091505b508093508192505050806132ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061596c602e913960400191505060405180910390fd5b6132b6826000614224565b92505050919050565b6000806133e36132cd615440565b73ffffffffffffffffffffffffffffffffffffffff16638d9a5e6f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561331257600080fd5b505afa158015613326573d6000803e3d6000fd5b505050506040513d602081101561333c57600080fd5b8101908080519060200190929190505050613355615551565b73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561339a57600080fd5b505afa1580156133ae573d6000803e3d6000fd5b505050506040513d60208110156133c457600080fd5b8101908080519060200190929190505050614b1890919063ffffffff16565b905060006133ef61423b565b73ffffffffffffffffffffffffffffffffffffffff16639a0e7d666040518163ffffffff1660e01b815260040160206040518083038186803b15801561343457600080fd5b505afa158015613448573d6000803e3d6000fd5b505050506040513d602081101561345e57600080fd5b8101908080519060200190929190505050905061349c61349761348084614336565b61348984614336565b61525090919063ffffffff16565b614216565b9250505090565b6134ab612aef565b61351d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156135c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b60006136686009604051806020016040529081600082015481525050614216565b905090565b6000613677612aef565b6136e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613708600a604051806020016040529081600082015481525050614216565b8214158015613725575061372261371d614878565b614216565b82105b61372e57600080fd5b6137378261489e565b600a600082015181600001559050507fe6c1b64ad7e601924731051286b7b408b1a6f3ae96dcd6d2d9cd82578372ef9e826040518082815260200191505060405180910390a160019050919050565b6000613790612aef565b613802576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61380a615930565b6138138361489e565b905061384160066002016040518060200160405290816000820154815250508261553b90919063ffffffff16565b613896576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180615b8f6035913960400191505060405180910390fd5b806006600001600082015181600001559050507f152c3fc1e1cd415804bc9ae15876b37e62d8909358b940e6f4847ca927f46637836040518082815260200191505060405180910390a16001915050919050565b60006060600060f873ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040518082805190602001908083835b60208310613950578051825260208201915060208101905060208303925061392d565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146139b0576040519150601f19603f3d011682016040523d82523d6000602084013e6139b5565b606091505b50809350819250505080613a14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615c426025913960400191505060405180910390fd5b613a1f826000614224565b9250505090565b600d5481565b6000613a706003613a626002613a546002613a4688613176565b6149b790919063ffffffff16565b614b6290919063ffffffff16565b614a3d90919063ffffffff16565b9050919050565b60008060008714158015613a8c575060008514155b613afe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310613b985780518252602082019150602081019050602083039250613b75565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613bf8576040519150601f19603f3d011682016040523d82523d6000602084013e613bfd565b606091505b50809250819350505081613c5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180615c1b6027913960400191505060405180910390fd5b613c67816000614224565b9350613c74816020614224565b925083839550955050505050965096945050505050565b613c93612aef565b613d05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613d0e81614cfa565b50565b60006060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310613d825780518252602082019150602081019050602083039250613d5f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613de2576040519150601f19603f3d011682016040523d82523d6000602084013e613de7565b606091505b50809350819250505080613e46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615c67602c913960400191505060405180910390fd5b613e51826000614a87565b92505050919050565b600080613e656113ca565b90506000613e7161167a565b90506000613e888284614b6290919063ffffffff16565b9050613f06613f01613eea600b604051806020016040529081600082015481525050613edc600a604051806020016040529081600082015481525050613ece6001614336565b61539990919063ffffffff16565b61539990919063ffffffff16565b613ef384614336565b61525090919063ffffffff16565b61481f565b905080935050505090565b613f19615930565b6000613f23611a1e565b90506000613f2f615551565b73ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f7457600080fd5b505afa158015613f88573d6000803e3d6000fd5b505050506040513d6020811015613f9e57600080fd5b810190808051906020019092919050505090506000613fe4613fc98684614b6290919063ffffffff16565b6b033b2e3c9fd0803ce8000000614b1890919063ffffffff16565b90506000614007846b033b2e3c9fd0803ce8000000614b1890919063ffffffff16565b9050614011615930565b61403461401d83614336565b61402685614336565b61525090919063ffffffff16565b9050614050614041614878565b8261564c90919063ffffffff16565b156141335761405d615930565b6140a56003600001600001604051806020016040529081600082015481525050614097614088614878565b8561539990919063ffffffff16565b6143c090919063ffffffff16565b90506140af615930565b6140c9826140bb614878565b61566190919063ffffffff16565b90506140f7600360020160405180602001604052908160008201548152505082614bea90919063ffffffff16565b1561410b5780975050505050505050614211565b6003600201604051806020016040529081600082015481525050975050505050505050614211565b61414d61413e614878565b82614bea90919063ffffffff16565b156142015761415a615930565b6141a2600360000160010160405180602001604052908160008201548152505061419484614186614878565b61539990919063ffffffff16565b6143c090919063ffffffff16565b90506141be6141af614878565b82614bea90919063ffffffff16565b156141ea576141dd816141cf614878565b61539990919063ffffffff16565b9650505050505050614211565b6141f4600061489e565b9650505050505050614211565b614209614878565b955050505050505b919050565b600081600001519050919050565b60006142308383614a87565b60001c905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f456c656374696f6e0000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156142f657600080fd5b505afa15801561430a573d6000803e3d6000fd5b505050506040513d602081101561432057600080fd5b8101908080519060200190929190505050905090565b61433e615930565b61434661570a565b82111561439e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180615ac56036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b6143c8615930565b6000836000015114806143df575060008260000151145b156143fb57604051806020016040528060008152509050614819565b69d3c21bcecceda10000008260000151141561441957829050614819565b69d3c21bcecceda10000008360000151141561443757819050614819565b600069d3c21bcecceda100000061444d85615729565b600001518161445857fe5b049050600061446685615760565b600001519050600069d3c21bcecceda100000061448286615729565b600001518161448d57fe5b049050600061449b86615760565b600001519050600082850290506000851461452f57828582816144ba57fe5b041461452e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda100000082029050600082146145d15769d3c21bcecceda100000082828161455c57fe5b04146145d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b809150600084860290506000861461466257848682816145ed57fe5b0414614661576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b60008488029050600088146146f0578488828161467b57fe5b04146146ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b6146f861579d565b878161470057fe5b04965061470b61579d565b858161471357fe5b04945060008588029050600088146147a4578588828161472f57fe5b04146147a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b6147ac615930565b60405180602001604052808781525090506147d581604051806020016040528087815250615661565b90506147ef81604051806020016040528086815250615661565b905061480981604051806020016040528085815250615661565b9050809a50505050505050505050505b92915050565b600069d3c21bcecceda100000082600001518161483857fe5b049050919050565b60008082848161484c57fe5b049050600083858161485a57fe5b06141561486a5780915050614872565b600181019150505b92915050565b614880615930565b604051806020016040528069d3c21bcecceda1000000815250905090565b6148a6615930565b6040518060200160405280838152509050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f536f727465644f7261636c657300000000000000000000000000000000000000815250600d019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561497757600080fd5b505afa15801561498b573d6000803e3d6000fd5b505050506040513d60208110156149a157600080fd5b8101908080519060200190929190505050905090565b6000808314156149ca5760009050614a37565b60008284029050828482816149db57fe5b0414614a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615bfa6021913960400191505060405180910390fd5b809150505b92915050565b6000614a7f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506157aa565b905092915050565b60006020820183511015614b03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b6000614b5a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615870565b905092915050565b600080828401905083811015614be0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60008160000151836000015110905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f467265657a6572000000000000000000000000000000000000000000000000008152506007019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614cba57600080fd5b505afa158015614cce573d6000803e3d6000fd5b505050506040513d6020811015614ce457600080fd5b8101908080519060200190929190505050905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614d80576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806159e06026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b614e4e614bff565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015614eca57600080fd5b505afa158015614ede573d6000803e3d6000fd5b505050506040513d6020811015614ef457600080fd5b810190808051906020019092919050505015614f5b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615aa36022913960400191505060405180910390fd5b614f63615930565b614f73614f6e6132bf565b61489e565b9050614f9e60096040518060200160405290816000820154815250508261564c90919063ffffffff16565b156150a457614fab615930565b614fd460096040518060200160405290816000820154815250508361539990919063ffffffff16565b9050614fde615930565b61500a6006600101604051806020016040529081600082015481525050836143c090919063ffffffff16565b905061503860066000016040518060200160405290816000820154815250508261523a90919063ffffffff16565b1561505e576150476000614336565b60066000016000820151816000015590505061509d565b61508a81600660000160405180602001604052908160008201548152505061539990919063ffffffff16565b6006600001600082015181600001559050505b50506151df565b6150cd600960405180602001604052908160008201548152505082614bea90919063ffffffff16565b156151de576150da615930565b61510382600960405180602001604052908160008201548152505061539990919063ffffffff16565b905061510d615930565b6151396006600101604051806020016040529081600082015481525050836143c090919063ffffffff16565b905061516781600660000160405180602001604052908160008201548152505061566190919063ffffffff16565b6006600001600082015181600001559050506151be6006600201604051806020016040529081600082015481525050600660000160405180602001604052908160008201548152505061564c90919063ffffffff16565b156151db5760066002016006600001600082015481600001559050505b50505b5b7f49d8cdfe05bae61517c234f65f4088454013bafe561115126a8fe0074dc7700e6152226006600001604051806020016040529081600082015481525050614216565b6040518082815260200191505060405180910390a150565b6000816000015183600001511015905092915050565b615258615930565b6000826000015114156152d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f63616e277420646976696465206279203000000000000000000000000000000081525060200191505060405180910390fd5b600069d3c21bcecceda10000008460000151029050836000015169d3c21bcecceda1000000828161530057fe5b0414615374576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6f766572666c6f7720617420646976696465000000000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808460000151838161538c57fe5b0481525091505092915050565b6153a1615930565b81600001518360000151101561541f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f737562737472616374696f6e20756e646572666c6f772064657465637465640081525060200191505060405180910390fd5b60405180602001604052808360000151856000015103815250905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f52657365727665000000000000000000000000000000000000000000000000008152506007019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156154fb57600080fd5b505afa15801561550f573d6000803e3d6000fd5b505050506040513d602081101561552557600080fd5b8101908080519060200190929190505050905090565b6000816000015183600001511115905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561560c57600080fd5b505afa158015615620573d6000803e3d6000fd5b505050506040513d602081101561563657600080fd5b8101908080519060200190929190505050905090565b60008160000151836000015111905092915050565b615669615930565b60008260000151846000015101905083600001518110156156f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b615731615930565b604051806020016040528069d3c21bcecceda10000008085600001518161575457fe5b04028152509050919050565b615768615930565b604051806020016040528069d3c21bcecceda10000008085600001518161578b57fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b60008083118290615856576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561581b578082015181840152602081019050615800565b50505050905090810190601f1680156158485780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161586257fe5b049050809150509392505050565b600083831115829061591d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158e25780820151818401526020810190506158c7565b50505050905090810190601f16801561590f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b604051806020016040528060008152509056fe5461726765742076616c696461746f722065706f6368207061796d656e7420756e6368616e6765646572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c654261642072657761726473206d756c7469706c69657220706172616d657465727354617267657420766f74696e6720676f6c64206672616374696f6e20756e6368616e6765644f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737354617267657420766f74696e6720676f6c64206672616374696f6e2063616e6e6f74206265206c6172676572207468616e2031496d706c656d656e7420626c6f636b207265776172642063616c63756c6174696f6e20666f722079656172732031352d33306572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c6563616e27742063616c6c207768656e20636f6e74726163742069732066726f7a656e63616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e6577466978656428294261642074617267657420766f74696e67207969656c6420706172616d65746572736572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c6554617267657420766f74696e67207969656c64206d757374206265206c657373207468616e206f7220657175616c20746f206d61786572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c656572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c656572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c654d61782074617267657420766f74696e67207969656c64206d757374206265206c6f776572207468616e20313030256572726f722063616c6c696e67206861736848656164657220707265636f6d70696c65a165627a7a72305820130af7e533b5b625073d2c0191e3d00625ce0200ffe3e2e786e7b1a207eb20f20029