Address Details
contract

0xcDAE80ca3802171539Ce95e77FD2aD8ACc816e65

Contract Name
Attestations
Creator
0x0cc59e–f1502d at 0xfadf63–12a601
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
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
2158656
Contract name:
Attestations




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




Verified at
2020-08-11T18:45:05.631921Z

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

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

library SafeCast {

    
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
        return uint128(value);
    }

    
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
        return uint64(value);
    }

    
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
        return uint32(value);
    }

    
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
        return uint16(value);
    }

    
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
        return uint8(value);
    }
}

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

contract Initializable {
  bool public initialized;

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

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

library ECDSA {
    
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        
        if (signature.length != 65) {
            return (address(0));
        }

        
        bytes32 r;
        bytes32 s;
        uint8 v;

        
        
        
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        
        
        
        
        
        
        
        
        
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return address(0);
        }

        if (v != 27 && v != 28) {
            return address(0);
        }

        
        return ecrecover(hash, v, r, s);
    }

    
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        
        
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

library Signatures {
  
  function getSignerOfAddress(address message, uint8 v, bytes32 r, bytes32 s)
    public
    pure
    returns (address)
  {
    bytes32 hash = keccak256(abi.encodePacked(message));
    return getSignerOfMessageHash(hash, v, r, s);
  }

  
  function getSignerOfMessageHash(bytes32 messageHash, uint8 v, bytes32 r, bytes32 s)
    public
    pure
    returns (address)
  {
    bytes memory signature = new bytes(65);
    
    assembly {
      mstore(add(signature, 32), r)
      mstore(add(signature, 64), s)
      mstore8(add(signature, 96), v)
    }
    bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(messageHash);
    return ECDSA.recover(prefixedHash, signature);
  }
}

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 ReentrancyGuard {
  
  uint256 private _guardCounter;

  constructor() internal {
    
    
    _guardCounter = 1;
  }

  
  modifier nonReentrant() {
    _guardCounter += 1;
    uint256 localCounter = _guardCounter;
    _;
    require(localCounter == _guardCounter, "reentrant call");
  }
}

contract Attestations is
  IAttestations,
  Ownable,
  Initializable,
  UsingRegistry,
  ReentrancyGuard,
  UsingPrecompiles
{
  using SafeMath for uint256;
  using SafeCast for uint256;

  enum AttestationStatus { None, Incomplete, Complete }

  struct Attestation {
    AttestationStatus status;
    
    
    uint32 blockNumber;
    
    address attestationRequestFeeToken;
  }

  
  struct AttestedAddress {
    
    uint32 requested;
    
    uint32 completed;
    
    
    
    address[] selectedIssuers;
    
    mapping(address => Attestation) issuedAttestations;
  }

  struct UnselectedRequest {
    
    uint32 blockNumber;
    
    uint32 attestationsRequested;
    
    address attestationRequestFeeToken;
  }

  struct IdentifierState {
    
    address[] accounts;
    
    mapping(address => AttestedAddress) attestations;
    
    mapping(address => UnselectedRequest) unselectedRequests;
  }

  mapping(bytes32 => IdentifierState) identifiers;

  
  
  uint256 public attestationExpiryBlocks;

  
  uint256 public selectIssuersWaitBlocks;

  
  uint256 public maxAttestations;

  
  mapping(address => uint256) public attestationRequestFees;

  
  mapping(address => mapping(address => uint256)) public pendingWithdrawals;

  event AttestationsRequested(
    bytes32 indexed identifier,
    address indexed account,
    uint256 attestationsRequested,
    address attestationRequestFeeToken
  );

  event AttestationIssuerSelected(
    bytes32 indexed identifier,
    address indexed account,
    address indexed issuer,
    address attestationRequestFeeToken
  );

  event AttestationCompleted(
    bytes32 indexed identifier,
    address indexed account,
    address indexed issuer
  );

  event Withdrawal(address indexed account, address indexed token, uint256 amount);
  event AttestationExpiryBlocksSet(uint256 value);
  event AttestationRequestFeeSet(address indexed token, uint256 value);
  event SelectIssuersWaitBlocksSet(uint256 value);
  event MaxAttestationsSet(uint256 value);

  
  function initialize(
    address registryAddress,
    uint256 _attestationExpiryBlocks,
    uint256 _selectIssuersWaitBlocks,
    uint256 _maxAttestations,
    address[] calldata attestationRequestFeeTokens,
    uint256[] calldata attestationRequestFeeValues
  ) external initializer {
    _transferOwnership(msg.sender);
    setRegistry(registryAddress);
    setAttestationExpiryBlocks(_attestationExpiryBlocks);
    setSelectIssuersWaitBlocks(_selectIssuersWaitBlocks);
    setMaxAttestations(_maxAttestations);

    require(
      attestationRequestFeeTokens.length > 0 &&
        attestationRequestFeeTokens.length == attestationRequestFeeValues.length,
      "attestationRequestFeeTokens specification was invalid"
    );
    for (uint256 i = 0; i < attestationRequestFeeTokens.length; i = i.add(1)) {
      setAttestationRequestFee(attestationRequestFeeTokens[i], attestationRequestFeeValues[i]);
    }
  }

  
  function request(
    bytes32 identifier,
    uint256 attestationsRequested,
    address attestationRequestFeeToken
  ) external nonReentrant {
    require(
      attestationRequestFees[attestationRequestFeeToken] > 0,
      "Invalid attestationRequestFeeToken"
    );
    require(
      IERC20(attestationRequestFeeToken).transferFrom(
        msg.sender,
        address(this),
        attestationRequestFees[attestationRequestFeeToken].mul(attestationsRequested)
      ),
      "Transfer of attestation request fees failed"
    );

    require(attestationsRequested > 0, "You have to request at least 1 attestation");
    require(attestationsRequested <= maxAttestations, "Too many attestations requested");

    IdentifierState storage state = identifiers[identifier];

    require(
      state.unselectedRequests[msg.sender].blockNumber == 0 ||
        isAttestationExpired(state.unselectedRequests[msg.sender].blockNumber) ||
        !isAttestationRequestSelectable(state.unselectedRequests[msg.sender].blockNumber),
      "There exists an unexpired, unselected attestation request"
    );

    state.unselectedRequests[msg.sender].blockNumber = block.number.toUint32();
    state.unselectedRequests[msg.sender].attestationsRequested = attestationsRequested.toUint32();
    state.unselectedRequests[msg.sender].attestationRequestFeeToken = attestationRequestFeeToken;

    state.attestations[msg.sender].requested = uint256(state.attestations[msg.sender].requested)
      .add(attestationsRequested)
      .toUint32();

    emit AttestationsRequested(
      identifier,
      msg.sender,
      attestationsRequested,
      attestationRequestFeeToken
    );
  }

  
  function selectIssuers(bytes32 identifier) external {
    IdentifierState storage state = identifiers[identifier];

    require(
      state.unselectedRequests[msg.sender].blockNumber > 0,
      "No unselected attestation request to select issuers for"
    );

    require(
      !isAttestationExpired(state.unselectedRequests[msg.sender].blockNumber),
      "The attestation request has expired"
    );

    addIncompleteAttestations(identifier);
    delete state.unselectedRequests[msg.sender];
  }

  
  function complete(bytes32 identifier, uint8 v, bytes32 r, bytes32 s) external {
    address issuer = validateAttestationCode(identifier, msg.sender, v, r, s);

    Attestation storage attestation = identifiers[identifier].attestations[msg.sender]
      .issuedAttestations[issuer];

    address token = attestation.attestationRequestFeeToken;

    
    attestation.blockNumber = block.number.toUint32();
    attestation.status = AttestationStatus.Complete;
    delete attestation.attestationRequestFeeToken;
    AttestedAddress storage attestedAddress = identifiers[identifier].attestations[msg.sender];
    require(
      attestedAddress.completed < attestedAddress.completed + 1,
      "SafeMath32 integer overflow"
    );
    attestedAddress.completed = attestedAddress.completed + 1;

    pendingWithdrawals[token][issuer] = pendingWithdrawals[token][issuer].add(
      attestationRequestFees[token]
    );

    IdentifierState storage state = identifiers[identifier];
    if (identifiers[identifier].attestations[msg.sender].completed == 1) {
      state.accounts.push(msg.sender);
    }

    emit AttestationCompleted(identifier, msg.sender, issuer);
  }

  
  function revoke(bytes32 identifier, uint256 index) external {
    uint256 numAccounts = identifiers[identifier].accounts.length;
    require(index < numAccounts, "Index is invalid");
    require(
      msg.sender == identifiers[identifier].accounts[index],
      "Index does not match msg.sender"
    );

    uint256 newNumAccounts = numAccounts.sub(1);
    if (index != newNumAccounts) {
      identifiers[identifier].accounts[index] = identifiers[identifier].accounts[newNumAccounts];
    }
    identifiers[identifier].accounts[newNumAccounts] = address(0x0);
    identifiers[identifier].accounts.length = identifiers[identifier].accounts.length.sub(1);
  }

  
  function withdraw(address token) external {
    uint256 value = pendingWithdrawals[token][msg.sender];
    require(value > 0, "value was negative/zero");
    pendingWithdrawals[token][msg.sender] = 0;
    require(IERC20(token).transfer(msg.sender, value), "token transfer failed");
    emit Withdrawal(msg.sender, token, value);
  }

  
  function getUnselectedRequest(bytes32 identifier, address account)
    external
    view
    returns (uint32, uint32, address)
  {
    return (
      identifiers[identifier].unselectedRequests[account].blockNumber,
      identifiers[identifier].unselectedRequests[account].attestationsRequested,
      identifiers[identifier].unselectedRequests[account].attestationRequestFeeToken
    );
  }

  
  function getAttestationIssuers(bytes32 identifier, address account)
    external
    view
    returns (address[] memory)
  {
    return identifiers[identifier].attestations[account].selectedIssuers;
  }

  
  function getAttestationStats(bytes32 identifier, address account)
    external
    view
    returns (uint32, uint32)
  {
    return (
      identifiers[identifier].attestations[account].completed,
      identifiers[identifier].attestations[account].requested
    );
  }

  
  function batchGetAttestationStats(bytes32[] calldata identifiersToLookup)
    external
    view
    returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory)
  {
    require(identifiersToLookup.length > 0, "You have to pass at least one identifier");

    uint256[] memory matches;
    address[] memory addresses;

    (matches, addresses) = batchlookupAccountsForIdentifier(identifiersToLookup);

    uint64[] memory completed = new uint64[](addresses.length);
    uint64[] memory total = new uint64[](addresses.length);

    uint256 currentIndex = 0;
    for (uint256 i = 0; i < identifiersToLookup.length; i = i.add(1)) {
      address[] memory addrs = identifiers[identifiersToLookup[i]].accounts;
      for (uint256 matchIndex = 0; matchIndex < matches[i]; matchIndex = matchIndex.add(1)) {
        addresses[currentIndex] = getAccounts().getWalletAddress(addrs[matchIndex]);
        completed[currentIndex] = identifiers[identifiersToLookup[i]]
          .attestations[addrs[matchIndex]]
          .completed;
        total[currentIndex] = identifiers[identifiersToLookup[i]].attestations[addrs[matchIndex]]
          .requested;
        currentIndex = currentIndex.add(1);
      }
    }

    return (matches, addresses, completed, total);
  }

  
  function getAttestationState(bytes32 identifier, address account, address issuer)
    external
    view
    returns (uint8, uint32, address)
  {
    Attestation storage attestation = identifiers[identifier].attestations[account]
      .issuedAttestations[issuer];
    return (
      uint8(attestation.status),
      attestation.blockNumber,
      attestation.attestationRequestFeeToken
    );

  }

  
  function getCompletableAttestations(bytes32 identifier, address account)
    external
    view
    returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory)
  {
    AttestedAddress storage state = identifiers[identifier].attestations[account];
    address[] storage issuers = state.selectedIssuers;

    uint256 num = 0;
    for (uint256 i = 0; i < issuers.length; i = i.add(1)) {
      if (isAttestationCompletable(state.issuedAttestations[issuers[i]])) {
        num = num.add(1);
      }
    }

    uint32[] memory blockNumbers = new uint32[](num);
    address[] memory completableIssuers = new address[](num);

    uint256 pointer = 0;
    for (uint256 i = 0; i < issuers.length; i = i.add(1)) {
      if (isAttestationCompletable(state.issuedAttestations[issuers[i]])) {
        blockNumbers[pointer] = state.issuedAttestations[issuers[i]].blockNumber;
        completableIssuers[pointer] = issuers[i];
        pointer = pointer.add(1);
      }
    }

    uint256[] memory stringLengths;
    bytes memory stringData;
    (stringLengths, stringData) = getAccounts().batchGetMetadataURL(completableIssuers);
    return (blockNumbers, completableIssuers, stringLengths, stringData);
  }

  
  function getAttestationRequestFee(address token) external view returns (uint256) {
    return attestationRequestFees[token];
  }

  
  function setAttestationRequestFee(address token, uint256 fee) public onlyOwner {
    require(fee > 0, "You have to specify a fee greater than 0");
    attestationRequestFees[token] = fee;
    emit AttestationRequestFeeSet(token, fee);
  }

  
  function setAttestationExpiryBlocks(uint256 _attestationExpiryBlocks) public onlyOwner {
    require(_attestationExpiryBlocks > 0, "attestationExpiryBlocks has to be greater than 0");
    attestationExpiryBlocks = _attestationExpiryBlocks;
    emit AttestationExpiryBlocksSet(_attestationExpiryBlocks);
  }

  
  function setSelectIssuersWaitBlocks(uint256 _selectIssuersWaitBlocks) public onlyOwner {
    require(_selectIssuersWaitBlocks > 0, "selectIssuersWaitBlocks has to be greater than 0");
    selectIssuersWaitBlocks = _selectIssuersWaitBlocks;
    emit SelectIssuersWaitBlocksSet(_selectIssuersWaitBlocks);
  }

  
  function setMaxAttestations(uint256 _maxAttestations) public onlyOwner {
    require(_maxAttestations > 0, "maxAttestations has to be greater than 0");
    maxAttestations = _maxAttestations;
    emit MaxAttestationsSet(_maxAttestations);
  }

  
  function getMaxAttestations() external view returns (uint256) {
    return maxAttestations;
  }

  
  function validateAttestationCode(
    bytes32 identifier,
    address account,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) public view returns (address) {
    bytes32 codehash = keccak256(abi.encodePacked(identifier, account));
    address signer = Signatures.getSignerOfMessageHash(codehash, v, r, s);
    address issuer = getAccounts().attestationSignerToAccount(signer);

    Attestation storage attestation = identifiers[identifier].attestations[account]
      .issuedAttestations[issuer];

    require(
      attestation.status == AttestationStatus.Incomplete,
      "Attestation code does not match any outstanding attestation"
    );
    require(!isAttestationExpired(attestation.blockNumber), "Attestation timed out");

    return issuer;
  }

  function lookupAccountsForIdentifier(bytes32 identifier)
    external
    view
    returns (address[] memory)
  {
    return identifiers[identifier].accounts;
  }

  
  function batchlookupAccountsForIdentifier(bytes32[] memory identifiersToLookup)
    internal
    view
    returns (uint256[] memory, address[] memory)
  {
    require(identifiersToLookup.length > 0, "You have to pass at least one identifier");
    uint256 totalAddresses = 0;
    uint256[] memory matches = new uint256[](identifiersToLookup.length);

    for (uint256 i = 0; i < identifiersToLookup.length; i = i.add(1)) {
      uint256 count = identifiers[identifiersToLookup[i]].accounts.length;

      totalAddresses = totalAddresses + count;
      matches[i] = count;
    }

    return (matches, new address[](totalAddresses));
  }

  
  function addIncompleteAttestations(bytes32 identifier) internal {
    AttestedAddress storage state = identifiers[identifier].attestations[msg.sender];
    UnselectedRequest storage unselectedRequest = identifiers[identifier].unselectedRequests[msg
      .sender];

    bytes32 seed = getRandom().getBlockRandomness(
      uint256(unselectedRequest.blockNumber).add(selectIssuersWaitBlocks)
    );
    IAccounts accounts = getAccounts();
    uint256 issuersLength = numberValidatorsInCurrentSet();
    uint256[] memory issuers = new uint256[](issuersLength);
    for (uint256 i = 0; i < issuersLength; i++) issuers[i] = i;

    require(unselectedRequest.attestationsRequested <= issuersLength, "not enough issuers");

    uint256 currentIndex = 0;

    
    
    while (currentIndex < unselectedRequest.attestationsRequested) {
      require(issuersLength > 0, "not enough issuers");
      seed = keccak256(abi.encodePacked(seed));
      uint256 idx = uint256(seed) % issuersLength;
      address signer = validatorSignerAddressFromCurrentSet(issuers[idx]);
      address issuer = accounts.signerToAccount(signer);

      Attestation storage attestation = state.issuedAttestations[issuer];

      if (
        attestation.status == AttestationStatus.None &&
        accounts.hasAuthorizedAttestationSigner(issuer)
      ) {
        currentIndex = currentIndex.add(1);
        attestation.status = AttestationStatus.Incomplete;
        attestation.blockNumber = unselectedRequest.blockNumber;
        attestation.attestationRequestFeeToken = unselectedRequest.attestationRequestFeeToken;
        state.selectedIssuers.push(issuer);

        emit AttestationIssuerSelected(
          identifier,
          msg.sender,
          issuer,
          unselectedRequest.attestationRequestFeeToken
        );
      }

      
      
      issuersLength = issuersLength.sub(1);
      issuers[idx] = issuers[issuersLength];
    }
  }

  function isAttestationExpired(uint128 attestationRequestBlock) internal view returns (bool) {
    return block.number >= uint256(attestationRequestBlock).add(attestationExpiryBlocks);
  }

  function isAttestationCompletable(Attestation storage attestation) internal view returns (bool) {
    return (attestation.status == AttestationStatus.Incomplete &&
      !isAttestationExpired(attestation.blockNumber));
  }

  function isAttestationRequestSelectable(uint256 attestationRequestBlock)
    internal
    view
    returns (bool)
  {
    return block.number < attestationRequestBlock.add(getRandom().randomnessBlockRetentionWindow());
  }
}
        

Contract ABI

[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":""}],"name":"lookupAccountsForIdentifier","inputs":[{"type":"bytes32","name":"identifier"}],"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":"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":"getEpochNumberOfBlock","inputs":[{"type":"uint256","name":"blockNumber"}],"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":"uint32[]","name":""},{"type":"address[]","name":""},{"type":"uint256[]","name":""},{"type":"bytes","name":""}],"name":"getCompletableAttestations","inputs":[{"type":"bytes32","name":"identifier"},{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"withdraw","inputs":[{"type":"address","name":"token"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint32","name":""},{"type":"uint32","name":""}],"name":"getAttestationStats","inputs":[{"type":"bytes32","name":"identifier"},{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"validateAttestationCode","inputs":[{"type":"bytes32","name":"identifier"},{"type":"address","name":"account"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":true},{"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":"address[]","name":""}],"name":"getAttestationIssuers","inputs":[{"type":"bytes32","name":"identifier"},{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getAttestationRequestFee","inputs":[{"type":"address","name":"token"}],"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":"getMaxAttestations","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"registry","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"maxAttestations","inputs":[],"constant":true},{"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":"selectIssuersWaitBlocks","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":"view","payable":false,"outputs":[{"type":"uint256[]","name":""},{"type":"address[]","name":""},{"type":"uint64[]","name":""},{"type":"uint64[]","name":""}],"name":"batchGetAttestationStats","inputs":[{"type":"bytes32[]","name":"identifiersToLookup"}],"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":"uint256","name":""}],"name":"numberValidatorsInSet","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setAttestationExpiryBlocks","inputs":[{"type":"uint256","name":"_attestationExpiryBlocks"}],"constant":false},{"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":"attestationExpiryBlocks","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":""},{"type":"uint32","name":""},{"type":"address","name":""}],"name":"getAttestationState","inputs":[{"type":"bytes32","name":"identifier"},{"type":"address","name":"account"},{"type":"address","name":"issuer"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"revoke","inputs":[{"type":"bytes32","name":"identifier"},{"type":"uint256","name":"index"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"attestationRequestFees","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMaxAttestations","inputs":[{"type":"uint256","name":"_maxAttestations"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"request","inputs":[{"type":"bytes32","name":"identifier"},{"type":"uint256","name":"attestationsRequested"},{"type":"address","name":"attestationRequestFeeToken"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochSize","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setSelectIssuersWaitBlocks","inputs":[{"type":"uint256","name":"_selectIssuersWaitBlocks"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"selectIssuers","inputs":[{"type":"bytes32","name":"identifier"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint32","name":""},{"type":"uint32","name":""},{"type":"address","name":""}],"name":"getUnselectedRequest","inputs":[{"type":"bytes32","name":"identifier"},{"type":"address","name":"account"}],"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":""}],"name":"pendingWithdrawals","inputs":[{"type":"address","name":""},{"type":"address","name":""}],"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":"nonpayable","payable":false,"outputs":[],"name":"setAttestationRequestFee","inputs":[{"type":"address","name":"token"},{"type":"uint256","name":"fee"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"getParentSealBitmap","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"complete","inputs":[{"type":"bytes32","name":"identifier"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"registryAddress"},{"type":"uint256","name":"_attestationExpiryBlocks"},{"type":"uint256","name":"_selectIssuersWaitBlocks"},{"type":"uint256","name":"_maxAttestations"},{"type":"address[]","name":"attestationRequestFeeTokens"},{"type":"uint256[]","name":"attestationRequestFeeValues"}],"constant":false},{"type":"event","name":"AttestationsRequested","inputs":[{"type":"bytes32","name":"identifier","indexed":true},{"type":"address","name":"account","indexed":true},{"type":"uint256","name":"attestationsRequested","indexed":false},{"type":"address","name":"attestationRequestFeeToken","indexed":false}],"anonymous":false},{"type":"event","name":"AttestationIssuerSelected","inputs":[{"type":"bytes32","name":"identifier","indexed":true},{"type":"address","name":"account","indexed":true},{"type":"address","name":"issuer","indexed":true},{"type":"address","name":"attestationRequestFeeToken","indexed":false}],"anonymous":false},{"type":"event","name":"AttestationCompleted","inputs":[{"type":"bytes32","name":"identifier","indexed":true},{"type":"address","name":"account","indexed":true},{"type":"address","name":"issuer","indexed":true}],"anonymous":false},{"type":"event","name":"Withdrawal","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"token","indexed":true},{"type":"uint256","name":"amount","indexed":false}],"anonymous":false},{"type":"event","name":"AttestationExpiryBlocksSet","inputs":[{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"AttestationRequestFeeSet","inputs":[{"type":"address","name":"token","indexed":true},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"SelectIssuersWaitBlocksSet","inputs":[{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"MaxAttestationsSet","inputs":[{"type":"uint256","name":"value","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

0x6080604052600062000016620000c260201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506001600281905550620000ca565b600033905090565b6171ba80620000da6000396000f3fe608060405234801561001057600080fd5b50600436106102955760003560e01c80638f32d59b11610167578063df4da461116100ce578063ec68307211610087578063ec68307214611424578063f2fde38b1461149f578063f3ff26c6146114e3578063fae8db0a14611531578063fb6a2e5314611573578063fd536f5d146115c257610295565b8063df4da4611461123c578063e02659ce1461125a578063e221932e14611288578063e3d0f66f146112b6578063e50e652d1461136a578063e831be58146113ac57610295565b8063b45eb7da11610120578063b45eb7da1461103a578063b5599cc614611058578063bb46942f14611126578063bd93f9981461115e578063be2c47a6146111b6578063d02e0f0c146111e457610295565b80638f32d59b14610da057806396357c0a14610dc25780639a7b3be714610f685780639b2b592f14610f86578063a6437e7314610fc8578063a91ee0dc14610ff657610295565b80635fc5c9161161020b5780637b103999116101c45780637b10399914610be35780638218c6fe14610c2d57806387ee8a0f14610c4b57806389d3528614610c695780638a88362614610c875780638da5cb5b14610d5657610295565b80635fc5c916146109d3578063623d593114610a7657806367960e9114610ace578063715018a614610b9d5780637385e5da14610ba75780637796a68414610bc557610295565b80634b2c2f441161025d5780634b2c2f44146105795780634eef7e851461064857806351cff8d9146107e7578063596abea51461082b5780635ce9bc07146108ac5780635d180adb1461095b57610295565b806303cc1aff1461029a578063123633ea1461031d578063158ef93e1461038b57806323f0ab65146103ad5780633b1eb4bf14610537575b600080fd5b6102c6600480360360208110156102b057600080fd5b81019080803590602001909291905050506116ce565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103095780820151818401526020810190506102ee565b505050509050019250505060405180910390f35b6103496004803603602081101561033357600080fd5b8101908080359060200190929190505050611772565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103936118c3565b604051808215151515815260200191505060405180910390f35b61051d600480360360608110156103c357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561040057600080fd5b82018360208201111561041257600080fd5b8035906020019184600183028401116401000000008311171561043457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561049757600080fd5b8201836020820111156104a957600080fd5b803590602001918460018302840111640100000000831117156104cb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506118d6565b604051808215151515815260200191505060405180910390f35b6105636004803603602081101561054d57600080fd5b8101908080359060200190929190505050611a8f565b6040518082815260200191505060405180910390f35b6106326004803603602081101561058f57600080fd5b81019080803590602001906401000000008111156105ac57600080fd5b8201836020820111156105be57600080fd5b803590602001918460018302840111640100000000831117156105e057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611aa9565b6040518082815260200191505060405180910390f35b6106946004803603604081101561065e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c3d565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156106e35780820151818401526020810190506106c8565b50505050905001858103845288818151815260200191508051906020019060200280838360005b8381101561072557808201518184015260208101905061070a565b50505050905001858103835287818151815260200191508051906020019060200280838360005b8381101561076757808201518184015260208101905061074c565b50505050905001858103825286818151815260200191508051906020019080838360005b838110156107a657808201518184015260208101905061078b565b50505050905090810190601f1680156107d35780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b610829600480360360208110156107fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612175565b005b6108776004803603604081101561084157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061248b565b604051808363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff1681526020019250505060405180910390f35b610919600480360360a08110156108c257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612567565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109916004803603604081101561097157600080fd5b8101908080359060200190929190803590602001909291905050506128f6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a1f600480360360408110156109e957600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a48565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610a62578082015181840152602081019050610a47565b505050509050019250505060405180910390f35b610ab860048036036020811015610a8c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b2d565b6040518082815260200191505060405180910390f35b610b8760048036036020811015610ae457600080fd5b8101908080359060200190640100000000811115610b0157600080fd5b820183602082011115610b1357600080fd5b80359060200191846001830284011164010000000083111715610b3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612b76565b6040518082815260200191505060405180910390f35b610ba5612d0a565b005b610baf612e43565b6040518082815260200191505060405180910390f35b610bcd612e53565b6040518082815260200191505060405180910390f35b610beb612e5d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c35612e83565b6040518082815260200191505060405180910390f35b610c53612e89565b6040518082815260200191505060405180910390f35b610c71612fd0565b6040518082815260200191505060405180910390f35b610d4060048036036020811015610c9d57600080fd5b8101908080359060200190640100000000811115610cba57600080fd5b820183602082011115610ccc57600080fd5b80359060200191846001830284011164010000000083111715610cee57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612fd6565b6040518082815260200191505060405180910390f35b610d5e61316a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610da8613193565b604051808215151515815260200191505060405180910390f35b610e3960048036036020811015610dd857600080fd5b8101908080359060200190640100000000811115610df557600080fd5b820183602082011115610e0757600080fd5b80359060200191846020830284011164010000000083111715610e2957600080fd5b90919293919293905050506131f1565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b83811015610e88578082015181840152602081019050610e6d565b50505050905001858103845288818151815260200191508051906020019060200280838360005b83811015610eca578082015181840152602081019050610eaf565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610f0c578082015181840152602081019050610ef1565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610f4e578082015181840152602081019050610f33565b505050509050019850505050505050505060405180910390f35b610f706136fb565b6040518082815260200191505060405180910390f35b610fb260048036036020811015610f9c57600080fd5b810190808035906020019092919050505061370b565b6040518082815260200191505060405180910390f35b610ff460048036036020811015610fde57600080fd5b8101908080359060200190929190505050613854565b005b6110386004803603602081101561100c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613968565b005b611042613b0c565b6040518082815260200191505060405180910390f35b6110c46004803603606081101561106e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613b12565b604051808460ff1660ff1681526020018363ffffffff1663ffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390f35b61115c6004803603604081101561113c57600080fd5b810190808035906020019092919080359060200190929190505050613c14565b005b6111a06004803603602081101561117457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f28565b6040518082815260200191505060405180910390f35b6111e2600480360360208110156111cc57600080fd5b8101908080359060200190929190505050613f40565b005b61123a600480360360608110156111fa57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614054565b005b611244614841565b6040518082815260200191505060405180910390f35b6112866004803603602081101561127057600080fd5b810190808035906020019092919050505061497d565b005b6112b46004803603602081101561129e57600080fd5b8101908080359060200190929190505050614a91565b005b611302600480360360408110156112cc57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614cba565b604051808463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390f35b6113966004803603602081101561138057600080fd5b8101908080359060200190929190505050614e11565b6040518082815260200191505060405180910390f35b61140e600480360360408110156113c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614e5c565b6040518082815260200191505060405180910390f35b611482600480360360c081101561143a57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050614e81565b604051808381526020018281526020019250505060405180910390f35b6114e1600480360360208110156114b557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615095565b005b61152f600480360360408110156114f957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061511b565b005b61155d6004803603602081101561154757600080fd5b8101908080359060200190929190505050615284565b6040518082815260200191505060405180910390f35b6115c06004803603608081101561158957600080fd5b8101908080359060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506153cd565b005b6116cc600480360360c08110156115d857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561163357600080fd5b82018360208201111561164557600080fd5b8035906020019184602083028401116401000000008311171561166757600080fd5b90919293919293908035906020019064010000000081111561168857600080fd5b82018360208201111561169a57600080fd5b803590602001918460208302840111640100000000831117156116bc57600080fd5b90919293919293905050506158fc565b005b60606003600083815260200190815260200160002060000180548060200260200160405190810160405280929190818152602001828054801561176657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161171c575b50505050509050919050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106117eb57805182526020820191506020810190506020830392506117c8565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461184b576040519150601f19603f3d011682016040523d82523d6000602084013e611850565b606091505b508093508192505050806118af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180616eb7603d913960400191505060405180910390fd5b6118ba826000615aaf565b92505050919050565b600060149054906101000a900460ff1681565b60008060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b6020831061195f578051825260208201915060208101905060208303925061193c565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b602083106119b0578051825260208201915060208101905060208303925061198d565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b60208310611a1957805182526020820191506020810190506020830392506119f6565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611a79576040519150601f19603f3d011682016040523d82523d6000602084013e611a7e565b606091505b505080915050809150509392505050565b6000611aa282611a9d614841565b615ac6565b9050919050565b60006060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310611afe5780518252602082019150602081019050602083039250611adb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310611b655780518252602082019150602081019050602083039250611b42565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611bc5576040519150601f19603f3d011682016040523d82523d6000602084013e611bca565b606091505b50809350819250505080611c29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180616e556038913960400191505060405180910390fd5b611c34826000615afe565b92505050919050565b60608060608060006003600088815260200190815260200160002060010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816001019050600080905060008090505b8280549050811015611d6f57611d38846002016000858481548110611cce57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615b8f565b15611d5457611d51600183615bef90919063ffffffff16565b91505b611d68600182615bef90919063ffffffff16565b9050611cad565b50606081604051908082528060200260200182016040528015611da15781602001602082028038833980820191505090505b509050606082604051908082528060200260200182016040528015611dd55781602001602082028038833980820191505090505b509050600080905060008090505b8580549050811015611fd357611e6e876002016000888481548110611e0457fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615b8f565b15611fb857866002016000878381548110611e8557fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900463ffffffff16848381518110611f0a57fe5b602002602001019063ffffffff16908163ffffffff1681525050858181548110611f3057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838381518110611f6757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611fb5600183615bef90919063ffffffff16565b91505b611fcc600182615bef90919063ffffffff16565b9050611de3565b50606080611fdf615c77565b73ffffffffffffffffffffffffffffffffffffffff16638adaf96f856040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561204d578082015181840152602081019050612032565b505050509050019250505060006040518083038186803b15801561207057600080fd5b505afa158015612084573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060408110156120ae57600080fd5b8101908080516401000000008111156120c657600080fd5b828101905060208101848111156120dc57600080fd5b81518560208202830111640100000000821117156120f957600080fd5b5050929190602001805164010000000081111561211557600080fd5b8281019050602081018481111561212b57600080fd5b815185600182028301116401000000008211171561214857600080fd5b50509291905050508092508193505050848483839b509b509b509b50505050505050505092959194509250565b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811161226c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f76616c756520776173206e656761746976652f7a65726f00000000000000000081525060200191505060405180910390fd5b6000600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561237557600080fd5b505af1158015612389573d6000803e3d6000fd5b505050506040513d602081101561239f57600080fd5b8101908080519060200190929190505050612422576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f746f6b656e207472616e73666572206661696c6564000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398836040518082815260200191505060405180910390a35050565b6000806003600085815260200190815260200160002060010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff166003600086815260200190815260200160002060010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff16915091509250929050565b6000808686604051602001808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050600073415406e7b0b8a511f4e9111c34793cb0b465f8e363b3abdb0c838888886040518563ffffffff1660e01b8152600401808581526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561263957600080fd5b505af415801561264d573d6000803e3d6000fd5b505050506040513d602081101561266357600080fd5b810190808051906020019092919050505090506000612680615c77565b73ffffffffffffffffffffffffffffffffffffffff16637b2434cb836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156126fc57600080fd5b505afa158015612710573d6000803e3d6000fd5b505050506040513d602081101561272657600080fd5b810190808051906020019092919050505090506000600360008b815260200190815260200160002060010160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600160028111156127dd57fe5b8160000160009054906101000a900460ff1660028111156127fa57fe5b14612850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b815260200180616f29603b913960400191505060405180910390fd5b6128738160000160019054906101000a900463ffffffff1663ffffffff16615d72565b156128e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4174746573746174696f6e2074696d6564206f7574000000000000000000000081525060200191505060405180910390fd5b8194505050505095945050505050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061296f578051825260208201915060208101905060208303925061294c565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146129cf576040519150601f19603f3d011682016040523d82523d6000602084013e6129d4565b606091505b50809350819250505080612a33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180616f646036913960400191505060405180910390fd5b612a3e826000615aaf565b9250505092915050565b60606003600084815260200190815260200160002060010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015612b2057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311612ad6575b5050505050905092915050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310612bcb5780518252602082019150602081019050602083039250612ba8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310612c325780518252602082019150602081019050602083039250612c0f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612c92576040519150601f19603f3d011682016040523d82523d6000602084013e612c97565b606091505b50809350819250505080612cf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061716c6023913960400191505060405180910390fd5b612d01826000615afe565b92505050919050565b612d12613193565b612d84576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000612e4e43614e11565b905090565b6000600654905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310612efa5780518252602082019150602081019050602083039250612ed7565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612f5a576040519150601f19603f3d011682016040523d82523d6000602084013e612f5f565b606091505b50809350819250505080612fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180616ef46035913960400191505060405180910390fd5b612fc9826000615aaf565b9250505090565b60055481565b60006060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b6020831061302b5780518252602082019150602081019050602083039250613008565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310613092578051825260208201915060208101905060208303925061306f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146130f2576040519150601f19603f3d011682016040523d82523d6000602084013e6130f7565b606091505b50809350819250505080613156576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806171156031913960400191505060405180910390fd5b613161826000615aaf565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166131d5615da5565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60608060608060008686905011613253576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616fe66028913960400191505060405180910390fd5b6060806132a0888880806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050615dad565b8092508193505050606081516040519080825280602002602001820160405280156132da5781602001602082028038833980820191505090505b5090506060825160405190808252806020026020018201604052801561330f5781602001602082028038833980820191505090505b509050600080905060008090505b8b8b90508110156136e0576060600360008e8e8581811061333a57fe5b9050602002013581526020019081526020016000206000018054806020026020016040519081016040528092919081815260200182805480156133d257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311613388575b5050505050905060008090505b8783815181106133eb57fe5b60200260200101518110156136c357613402615c77565b73ffffffffffffffffffffffffffffffffffffffff16631fd9afa583838151811061342957fe5b60200260200101516040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561349157600080fd5b505afa1580156134a5573d6000803e3d6000fd5b505050506040513d60208110156134bb57600080fd5b81019080805190602001909291905050508785815181106134d857fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600360008f8f8681811061352257fe5b905060200201358152602001908152602001600020600101600083838151811061354857fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff168685815181106135b057fe5b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050600360008f8f868181106135e257fe5b905060200201358152602001908152602001600020600101600083838151811061360857fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1685858151811061367057fe5b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506136a6600185615bef90919063ffffffff16565b93506136bc600182615bef90919063ffffffff16565b90506133df565b50506136d9600182615bef90919063ffffffff16565b905061331d565b50848484849850985098509850505050505092959194509250565b600061370643611a8f565b905090565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061377c5780518252602082019150602081019050602083039250613759565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146137dc576040519150601f19603f3d011682016040523d82523d6000602084013e6137e1565b606091505b50809350819250505080613840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616d40602e913960400191505060405180910390fd5b61384b826000615aaf565b92505050919050565b61385c613193565b6138ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111613927576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180616e256030913960400191505060405180910390fd5b806004819055507f4fbe976a07a9260091c2d347f8780c4bc636392e34d5b249b367baf8a5c7ca69816040518082815260200191505060405180910390a150565b613970613193565b6139e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613a85576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b60045481565b6000806000806003600088815260200190815260200160002060010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff166002811115613bca57fe5b8160000160019054906101000a900463ffffffff168260000160059054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350935093505093509350939050565b600060036000848152602001908152602001600020600001805490509050808210613ca7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f496e64657820697320696e76616c69640000000000000000000000000000000081525060200191505060405180910390fd5b600360008481526020019081526020016000206000018281548110613cc857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f496e64657820646f6573206e6f74206d61746368206d73672e73656e6465720081525060200191505060405180910390fd5b6000613da9600183615efe90919063ffffffff16565b9050808314613e6857600360008581526020019081526020016000206000018181548110613dd357fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360008681526020019081526020016000206000018481548110613e1f57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6000600360008681526020019081526020016000206000018281548110613e8b57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613f0060016003600087815260200190815260200160002060000180549050615efe90919063ffffffff16565b6003600086815260200190815260200160002060000181613f219190616ca4565b5050505050565b60076020528060005260406000206000915090505481565b613f48613193565b613fba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111614013576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616cf66028913960400191505060405180910390fd5b806006819055507fc1f217a1246a98ce04e938768309107630ed86c1e0e9f9995af28e23a9c06178816040518082815260200191505060405180910390a150565b6001600260008282540192505081905550600060025490506000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411614104576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180616d1e6022913960400191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd333061417487600760008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054615f4890919063ffffffff16565b6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561421057600080fd5b505af1158015614224573d6000803e3d6000fd5b505050506040513d602081101561423a57600080fd5b81019080805190602001909291905050506142a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180616f9a602b913960400191505060405180910390fd5b600083116142f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180616e8d602a913960400191505060405180910390fd5b600654831115614371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f546f6f206d616e79206174746573746174696f6e73207265717565737465640081525060200191505060405180910390fd5b600060036000868152602001908152602001600020905060008160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff161480614450575061444f8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615d72565b5b806144bb57506144b98160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615fce565b155b614510576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526039815260200180616dc46039913960400191505060405180910390fd5b61451943616073565b8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff16021790555061458484616073565b8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160046101000a81548163ffffffff021916908363ffffffff160217905550828160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506146de6146d9858360010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615bef90919063ffffffff16565b616073565b8160010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16857f381545d9b1fffcb94ffbbd0bccfff9f1fb3acd474d34f7d59112a5c9973fee498686604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a350600254811461483b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b50505050565b60006060600060f873ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040518082805190602001908083835b602083106148a75780518252602082019150602081019050602083039250614884565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114614907576040519150601f19603f3d011682016040523d82523d6000602084013e61490c565b606091505b5080935081925050508061496b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806170356025913960400191505060405180910390fd5b614976826000615aaf565b9250505090565b614985613193565b6149f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111614a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180616d6e6030913960400191505060405180910390fd5b806005819055507f954fa47fa6f4e8017b99f93c73f4fbe599d786f9f5da73fe9086ab473fb455d8816040518082815260200191505060405180910390a150565b600060036000838152602001908152602001600020905060008160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1611614b5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260378152602001806170b26037913960400191505060405180910390fd5b614bbe8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615d72565b15614c14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061708f6023913960400191505060405180910390fd5b614c1d826160da565b8060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550505050565b60008060006003600086815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff166003600087815260200190815260200160002060020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff166003600088815260200190815260200160002060020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250925092509250925092565b6000614e556003614e476002614e396002614e2b8861370b565b615f4890919063ffffffff16565b615bef90919063ffffffff16565b61689590919063ffffffff16565b9050919050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60008060008714158015614e96575060008514155b614f08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310614fa25780518252602082019150602081019050602083039250614f7f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615002576040519150601f19603f3d011682016040523d82523d6000602084013e615007565b606091505b50809250819350505081615066576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061700e6027913960400191505060405180910390fd5b615071816000615aaf565b935061507e816020615aaf565b925083839550955050505050965096945050505050565b61509d613193565b61510f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b615118816168df565b50565b615123613193565b615195576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600081116151ee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616dfd6028913960400191505060405180910390fd5b80600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff167f7cf8b633f218e9f9bc2c06107bcaddcfee6b90580863768acdcfd4f05d7af394826040518082815260200191505060405180910390a25050565b60006060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106152f557805182526020820191506020810190506020830392506152d2565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615355576040519150601f19603f3d011682016040523d82523d6000602084013e61535a565b606091505b508093508192505050806153b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806170e9602c913960400191505060405180910390fd5b6153c4826000615afe565b92505050919050565b60006153dc8533868686612567565b905060006003600087815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160059054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506154a743616073565b8260000160016101000a81548163ffffffff021916908363ffffffff16021790555060028260000160006101000a81548160ff021916908360028111156154ea57fe5b02179055508160000160056101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560006003600089815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160049054906101000a900463ffffffff160163ffffffff168160000160049054906101000a900463ffffffff1663ffffffff1610615619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d617468333220696e7465676572206f766572666c6f77000000000081525060200191505060405180910390fd5b60018160000160049054906101000a900463ffffffff16018160000160046101000a81548163ffffffff021916908363ffffffff160217905550615721600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054615bef90919063ffffffff16565b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600360008a815260200190815260200160002090506001600360008b815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff16141561589657806000013390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168a7f414ff2c18c092697c4b8de49f515ac44f8bebc19b24553cf58ace913a6ac639d60405160405180910390a4505050505050505050565b600060149054906101000a900460ff161561597f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff0219169083151502179055506159a3336168df565b6159ac88613968565b6159b587613854565b6159be8661497d565b6159c785613f40565b6000848490501180156159df57508181905084849050145b615a34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061705a6035913960400191505060405180910390fd5b60008090505b84849050811015615aa457615a89858583818110615a5457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16848484818110615a7d57fe5b9050602002013561511b565b615a9d600182615bef90919063ffffffff16565b9050615a3a565b505050505050505050565b6000615abb8383615afe565b60001c905092915050565b600080828481615ad257fe5b0490506000838581615ae057fe5b061415615af05780915050615af8565b600181019150505b92915050565b60006020820183511015615b7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b600060016002811115615b9e57fe5b8260000160009054906101000a900460ff166002811115615bbb57fe5b148015615be85750615be68260000160019054906101000a900463ffffffff1663ffffffff16615d72565b155b9050919050565b600080828401905083811015615c6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4163636f756e74730000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015615d3257600080fd5b505afa158015615d46573d6000803e3d6000fd5b505050506040513d6020811015615d5c57600080fd5b8101908080519060200190929190505050905090565b6000615d9b600454836fffffffffffffffffffffffffffffffff16615bef90919063ffffffff16565b4310159050919050565b600033905090565b6060806000835111615e0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616fe66028913960400191505060405180910390fd5b600080905060608451604051908082528060200260200182016040528015615e415781602001602082028038833980820191505090505b50905060008090505b8551811015615ebe57600060036000888481518110615e6557fe5b60200260200101518152602001908152602001600020600001805490509050808401935080838381518110615e9657fe5b60200260200101818152505050615eb7600182615bef90919063ffffffff16565b9050615e4a565b508082604051908082528060200260200182016040528015615eef5781602001602082028038833980820191505090505b50809050935093505050915091565b6000615f4083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250616a23565b905092915050565b600080831415615f5b5760009050615fc8565b6000828402905082848281615f6c57fe5b0414615fc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180616fc56021913960400191505060405180910390fd5b809150505b92915050565b600061606a615fdb616ae3565b73ffffffffffffffffffffffffffffffffffffffff1663e45def956040518163ffffffff1660e01b815260040160206040518083038186803b15801561602057600080fd5b505afa158015616034573d6000803e3d6000fd5b505050506040513d602081101561604a57600080fd5b810190808051906020019092919050505083615bef90919063ffffffff16565b43109050919050565b600064010000000082106160d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806171466026913960400191505060405180910390fd5b819050919050565b60006003600083815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060006003600084815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000616192616ae3565b73ffffffffffffffffffffffffffffffffffffffff1663fc4847266161dc6005548560000160009054906101000a900463ffffffff1663ffffffff16615bef90919063ffffffff16565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561621057600080fd5b505afa158015616224573d6000803e3d6000fd5b505050506040513d602081101561623a57600080fd5b810190808051906020019092919050505090506000616257615c77565b90506000616263612e89565b90506060816040519080825280602002602001820160405280156162965781602001602082028038833980820191505090505b50905060008090505b828110156162cd57808282815181106162b457fe5b602002602001018181525050808060010191505061629f565b50818560000160049054906101000a900463ffffffff1663ffffffff16111561635e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6e6f7420656e6f7567682069737375657273000000000000000000000000000081525060200191505060405180910390fd5b60008090505b8560000160049054906101000a900463ffffffff1663ffffffff1681101561688b57600083116163fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6e6f7420656e6f7567682069737375657273000000000000000000000000000081525060200191505060405180910390fd5b84604051602001808281526020019150506040516020818303038152906040528051906020012094506000838660001c8161643357fe5b069050600061645484838151811061644757fe5b6020026020010151611772565b905060008673ffffffffffffffffffffffffffffffffffffffff166393c5c487836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156164d557600080fd5b505afa1580156164e9573d6000803e3d6000fd5b505050506040513d60208110156164ff57600080fd5b8101908080519060200190929190505050905060008a60020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600281111561656457fe5b8160000160009054906101000a900460ff16600281111561658157fe5b14801561664257508773ffffffffffffffffffffffffffffffffffffffff1663c2e0ee20836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561660657600080fd5b505afa15801561661a573d6000803e3d6000fd5b505050506040513d602081101561663057600080fd5b81019080805190602001909291905050505b156168405761665b600186615bef90919063ffffffff16565b945060018160000160006101000a81548160ff0219169083600281111561667e57fe5b02179055508960000160009054906101000a900463ffffffff168160000160016101000a81548163ffffffff021916908363ffffffff1602179055508960000160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160056101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a6001018290806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168d7faf7f470b643316cf44c1f2898328a075e7602945b4f8584f48ba4ad2d8a2ea9d8d60000160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a45b616854600188615efe90919063ffffffff16565b965085878151811061686257fe5b602002602001015186858151811061687657fe5b60200260200101818152505050505050616364565b5050505050505050565b60006168d783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250616bde565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415616965576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180616d9e6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000838311158290616ad0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015616a95578082015181840152602081019050616a7a565b50505050905090810190601f168015616ac25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f52616e646f6d00000000000000000000000000000000000000000000000000008152506006019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015616b9e57600080fd5b505afa158015616bb2573d6000803e3d6000fd5b505050506040513d6020811015616bc857600080fd5b8101908080519060200190929190505050905090565b60008083118290616c8a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015616c4f578082015181840152602081019050616c34565b50505050905090810190601f168015616c7c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581616c9657fe5b049050809150509392505050565b815481835581811115616ccb57818360005260206000209182019101616cca9190616cd0565b5b505050565b616cf291905b80821115616cee576000816000905550600101616cd6565b5090565b9056fe6d61784174746573746174696f6e732068617320746f2062652067726561746572207468616e2030496e76616c6964206174746573746174696f6e52657175657374466565546f6b656e6572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c6573656c6563744973737565727357616974426c6f636b732068617320746f2062652067726561746572207468616e20304f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737354686572652065786973747320616e20756e657870697265642c20756e73656c6563746564206174746573746174696f6e2072657175657374596f75206861766520746f20737065636966792061206665652067726561746572207468616e20306174746573746174696f6e457870697279426c6f636b732068617320746f2062652067726561746572207468616e20306572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c65596f75206861766520746f2072657175657374206174206c656173742031206174746573746174696f6e6572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c654174746573746174696f6e20636f646520646f6573206e6f74206d6174636820616e79206f75747374616e64696e67206174746573746174696f6e6572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c655472616e73666572206f66206174746573746174696f6e20726571756573742066656573206661696c6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77596f75206861766520746f2070617373206174206c65617374206f6e65206964656e7469666965726572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c656572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c656174746573746174696f6e52657175657374466565546f6b656e732073706563696669636174696f6e2077617320696e76616c6964546865206174746573746174696f6e20726571756573742068617320657870697265644e6f20756e73656c6563746564206174746573746174696f6e207265717565737420746f2073656c656374206973737565727320666f726572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c6553616665436173743a2076616c756520646f65736e27742066697420696e20333220626974736572726f722063616c6c696e67206861736848656164657220707265636f6d70696c65a165627a7a723058201ef00b4875bbe399c297607d5f84c5130ccff4db50536ec1730a190a9ed9dba90029

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106102955760003560e01c80638f32d59b11610167578063df4da461116100ce578063ec68307211610087578063ec68307214611424578063f2fde38b1461149f578063f3ff26c6146114e3578063fae8db0a14611531578063fb6a2e5314611573578063fd536f5d146115c257610295565b8063df4da4611461123c578063e02659ce1461125a578063e221932e14611288578063e3d0f66f146112b6578063e50e652d1461136a578063e831be58146113ac57610295565b8063b45eb7da11610120578063b45eb7da1461103a578063b5599cc614611058578063bb46942f14611126578063bd93f9981461115e578063be2c47a6146111b6578063d02e0f0c146111e457610295565b80638f32d59b14610da057806396357c0a14610dc25780639a7b3be714610f685780639b2b592f14610f86578063a6437e7314610fc8578063a91ee0dc14610ff657610295565b80635fc5c9161161020b5780637b103999116101c45780637b10399914610be35780638218c6fe14610c2d57806387ee8a0f14610c4b57806389d3528614610c695780638a88362614610c875780638da5cb5b14610d5657610295565b80635fc5c916146109d3578063623d593114610a7657806367960e9114610ace578063715018a614610b9d5780637385e5da14610ba75780637796a68414610bc557610295565b80634b2c2f441161025d5780634b2c2f44146105795780634eef7e851461064857806351cff8d9146107e7578063596abea51461082b5780635ce9bc07146108ac5780635d180adb1461095b57610295565b806303cc1aff1461029a578063123633ea1461031d578063158ef93e1461038b57806323f0ab65146103ad5780633b1eb4bf14610537575b600080fd5b6102c6600480360360208110156102b057600080fd5b81019080803590602001909291905050506116ce565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103095780820151818401526020810190506102ee565b505050509050019250505060405180910390f35b6103496004803603602081101561033357600080fd5b8101908080359060200190929190505050611772565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103936118c3565b604051808215151515815260200191505060405180910390f35b61051d600480360360608110156103c357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561040057600080fd5b82018360208201111561041257600080fd5b8035906020019184600183028401116401000000008311171561043457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561049757600080fd5b8201836020820111156104a957600080fd5b803590602001918460018302840111640100000000831117156104cb57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506118d6565b604051808215151515815260200191505060405180910390f35b6105636004803603602081101561054d57600080fd5b8101908080359060200190929190505050611a8f565b6040518082815260200191505060405180910390f35b6106326004803603602081101561058f57600080fd5b81019080803590602001906401000000008111156105ac57600080fd5b8201836020820111156105be57600080fd5b803590602001918460018302840111640100000000831117156105e057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611aa9565b6040518082815260200191505060405180910390f35b6106946004803603604081101561065e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611c3d565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b838110156106e35780820151818401526020810190506106c8565b50505050905001858103845288818151815260200191508051906020019060200280838360005b8381101561072557808201518184015260208101905061070a565b50505050905001858103835287818151815260200191508051906020019060200280838360005b8381101561076757808201518184015260208101905061074c565b50505050905001858103825286818151815260200191508051906020019080838360005b838110156107a657808201518184015260208101905061078b565b50505050905090810190601f1680156107d35780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b610829600480360360208110156107fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612175565b005b6108776004803603604081101561084157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061248b565b604051808363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff1681526020019250505060405180910390f35b610919600480360360a08110156108c257600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612567565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109916004803603604081101561097157600080fd5b8101908080359060200190929190803590602001909291905050506128f6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a1f600480360360408110156109e957600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a48565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610a62578082015181840152602081019050610a47565b505050509050019250505060405180910390f35b610ab860048036036020811015610a8c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b2d565b6040518082815260200191505060405180910390f35b610b8760048036036020811015610ae457600080fd5b8101908080359060200190640100000000811115610b0157600080fd5b820183602082011115610b1357600080fd5b80359060200191846001830284011164010000000083111715610b3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612b76565b6040518082815260200191505060405180910390f35b610ba5612d0a565b005b610baf612e43565b6040518082815260200191505060405180910390f35b610bcd612e53565b6040518082815260200191505060405180910390f35b610beb612e5d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c35612e83565b6040518082815260200191505060405180910390f35b610c53612e89565b6040518082815260200191505060405180910390f35b610c71612fd0565b6040518082815260200191505060405180910390f35b610d4060048036036020811015610c9d57600080fd5b8101908080359060200190640100000000811115610cba57600080fd5b820183602082011115610ccc57600080fd5b80359060200191846001830284011164010000000083111715610cee57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612fd6565b6040518082815260200191505060405180910390f35b610d5e61316a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610da8613193565b604051808215151515815260200191505060405180910390f35b610e3960048036036020811015610dd857600080fd5b8101908080359060200190640100000000811115610df557600080fd5b820183602082011115610e0757600080fd5b80359060200191846020830284011164010000000083111715610e2957600080fd5b90919293919293905050506131f1565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b83811015610e88578082015181840152602081019050610e6d565b50505050905001858103845288818151815260200191508051906020019060200280838360005b83811015610eca578082015181840152602081019050610eaf565b50505050905001858103835287818151815260200191508051906020019060200280838360005b83811015610f0c578082015181840152602081019050610ef1565b50505050905001858103825286818151815260200191508051906020019060200280838360005b83811015610f4e578082015181840152602081019050610f33565b505050509050019850505050505050505060405180910390f35b610f706136fb565b6040518082815260200191505060405180910390f35b610fb260048036036020811015610f9c57600080fd5b810190808035906020019092919050505061370b565b6040518082815260200191505060405180910390f35b610ff460048036036020811015610fde57600080fd5b8101908080359060200190929190505050613854565b005b6110386004803603602081101561100c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613968565b005b611042613b0c565b6040518082815260200191505060405180910390f35b6110c46004803603606081101561106e57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613b12565b604051808460ff1660ff1681526020018363ffffffff1663ffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390f35b61115c6004803603604081101561113c57600080fd5b810190808035906020019092919080359060200190929190505050613c14565b005b6111a06004803603602081101561117457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613f28565b6040518082815260200191505060405180910390f35b6111e2600480360360208110156111cc57600080fd5b8101908080359060200190929190505050613f40565b005b61123a600480360360608110156111fa57600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614054565b005b611244614841565b6040518082815260200191505060405180910390f35b6112866004803603602081101561127057600080fd5b810190808035906020019092919050505061497d565b005b6112b46004803603602081101561129e57600080fd5b8101908080359060200190929190505050614a91565b005b611302600480360360408110156112cc57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614cba565b604051808463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001935050505060405180910390f35b6113966004803603602081101561138057600080fd5b8101908080359060200190929190505050614e11565b6040518082815260200191505060405180910390f35b61140e600480360360408110156113c257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614e5c565b6040518082815260200191505060405180910390f35b611482600480360360c081101561143a57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190505050614e81565b604051808381526020018281526020019250505060405180910390f35b6114e1600480360360208110156114b557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615095565b005b61152f600480360360408110156114f957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061511b565b005b61155d6004803603602081101561154757600080fd5b8101908080359060200190929190505050615284565b6040518082815260200191505060405180910390f35b6115c06004803603608081101561158957600080fd5b8101908080359060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506153cd565b005b6116cc600480360360c08110156115d857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561163357600080fd5b82018360208201111561164557600080fd5b8035906020019184602083028401116401000000008311171561166757600080fd5b90919293919293908035906020019064010000000081111561168857600080fd5b82018360208201111561169a57600080fd5b803590602001918460208302840111640100000000831117156116bc57600080fd5b90919293919293905050506158fc565b005b60606003600083815260200190815260200160002060000180548060200260200160405190810160405280929190818152602001828054801561176657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161171c575b50505050509050919050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b602083106117eb57805182526020820191506020810190506020830392506117c8565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461184b576040519150601f19603f3d011682016040523d82523d6000602084013e611850565b606091505b508093508192505050806118af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180616eb7603d913960400191505060405180910390fd5b6118ba826000615aaf565b92505050919050565b600060149054906101000a900460ff1681565b60008060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b6020831061195f578051825260208201915060208101905060208303925061193c565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b602083106119b0578051825260208201915060208101905060208303925061198d565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b60208310611a1957805182526020820191506020810190506020830392506119f6565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611a79576040519150601f19603f3d011682016040523d82523d6000602084013e611a7e565b606091505b505080915050809150509392505050565b6000611aa282611a9d614841565b615ac6565b9050919050565b60006060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310611afe5780518252602082019150602081019050602083039250611adb565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310611b655780518252602082019150602081019050602083039250611b42565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114611bc5576040519150601f19603f3d011682016040523d82523d6000602084013e611bca565b606091505b50809350819250505080611c29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180616e556038913960400191505060405180910390fd5b611c34826000615afe565b92505050919050565b60608060608060006003600088815260200190815260200160002060010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816001019050600080905060008090505b8280549050811015611d6f57611d38846002016000858481548110611cce57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615b8f565b15611d5457611d51600183615bef90919063ffffffff16565b91505b611d68600182615bef90919063ffffffff16565b9050611cad565b50606081604051908082528060200260200182016040528015611da15781602001602082028038833980820191505090505b509050606082604051908082528060200260200182016040528015611dd55781602001602082028038833980820191505090505b509050600080905060008090505b8580549050811015611fd357611e6e876002016000888481548110611e0457fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615b8f565b15611fb857866002016000878381548110611e8557fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900463ffffffff16848381518110611f0a57fe5b602002602001019063ffffffff16908163ffffffff1681525050858181548110611f3057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16838381518110611f6757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050611fb5600183615bef90919063ffffffff16565b91505b611fcc600182615bef90919063ffffffff16565b9050611de3565b50606080611fdf615c77565b73ffffffffffffffffffffffffffffffffffffffff16638adaf96f856040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b8381101561204d578082015181840152602081019050612032565b505050509050019250505060006040518083038186803b15801561207057600080fd5b505afa158015612084573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060408110156120ae57600080fd5b8101908080516401000000008111156120c657600080fd5b828101905060208101848111156120dc57600080fd5b81518560208202830111640100000000821117156120f957600080fd5b5050929190602001805164010000000081111561211557600080fd5b8281019050602081018481111561212b57600080fd5b815185600182028301116401000000008211171561214857600080fd5b50509291905050508092508193505050848483839b509b509b509b50505050505050505092959194509250565b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811161226c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f76616c756520776173206e656761746976652f7a65726f00000000000000000081525060200191505060405180910390fd5b6000600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561237557600080fd5b505af1158015612389573d6000803e3d6000fd5b505050506040513d602081101561239f57600080fd5b8101908080519060200190929190505050612422576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f746f6b656e207472616e73666572206661696c6564000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398836040518082815260200191505060405180910390a35050565b6000806003600085815260200190815260200160002060010160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff166003600086815260200190815260200160002060010160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff16915091509250929050565b6000808686604051602001808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140192505050604051602081830303815290604052805190602001209050600073415406e7b0b8a511f4e9111c34793cb0b465f8e363b3abdb0c838888886040518563ffffffff1660e01b8152600401808581526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561263957600080fd5b505af415801561264d573d6000803e3d6000fd5b505050506040513d602081101561266357600080fd5b810190808051906020019092919050505090506000612680615c77565b73ffffffffffffffffffffffffffffffffffffffff16637b2434cb836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156126fc57600080fd5b505afa158015612710573d6000803e3d6000fd5b505050506040513d602081101561272657600080fd5b810190808051906020019092919050505090506000600360008b815260200190815260200160002060010160008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600160028111156127dd57fe5b8160000160009054906101000a900460ff1660028111156127fa57fe5b14612850576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603b815260200180616f29603b913960400191505060405180910390fd5b6128738160000160019054906101000a900463ffffffff1663ffffffff16615d72565b156128e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4174746573746174696f6e2074696d6564206f7574000000000000000000000081525060200191505060405180910390fd5b8194505050505095945050505050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061296f578051825260208201915060208101905060208303925061294c565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146129cf576040519150601f19603f3d011682016040523d82523d6000602084013e6129d4565b606091505b50809350819250505080612a33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180616f646036913960400191505060405180910390fd5b612a3e826000615aaf565b9250505092915050565b60606003600084815260200190815260200160002060010160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015612b2057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311612ad6575b5050505050905092915050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60006060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310612bcb5780518252602082019150602081019050602083039250612ba8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310612c325780518252602082019150602081019050602083039250612c0f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612c92576040519150601f19603f3d011682016040523d82523d6000602084013e612c97565b606091505b50809350819250505080612cf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061716c6023913960400191505060405180910390fd5b612d01826000615afe565b92505050919050565b612d12613193565b612d84576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000612e4e43614e11565b905090565b6000600654905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60065481565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310612efa5780518252602082019150602081019050602083039250612ed7565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612f5a576040519150601f19603f3d011682016040523d82523d6000602084013e612f5f565b606091505b50809350819250505080612fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526035815260200180616ef46035913960400191505060405180910390fd5b612fc9826000615aaf565b9250505090565b60055481565b60006060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b6020831061302b5780518252602082019150602081019050602083039250613008565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310613092578051825260208201915060208101905060208303925061306f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146130f2576040519150601f19603f3d011682016040523d82523d6000602084013e6130f7565b606091505b50809350819250505080613156576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806171156031913960400191505060405180910390fd5b613161826000615aaf565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166131d5615da5565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60608060608060008686905011613253576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616fe66028913960400191505060405180910390fd5b6060806132a0888880806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050615dad565b8092508193505050606081516040519080825280602002602001820160405280156132da5781602001602082028038833980820191505090505b5090506060825160405190808252806020026020018201604052801561330f5781602001602082028038833980820191505090505b509050600080905060008090505b8b8b90508110156136e0576060600360008e8e8581811061333a57fe5b9050602002013581526020019081526020016000206000018054806020026020016040519081016040528092919081815260200182805480156133d257602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311613388575b5050505050905060008090505b8783815181106133eb57fe5b60200260200101518110156136c357613402615c77565b73ffffffffffffffffffffffffffffffffffffffff16631fd9afa583838151811061342957fe5b60200260200101516040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561349157600080fd5b505afa1580156134a5573d6000803e3d6000fd5b505050506040513d60208110156134bb57600080fd5b81019080805190602001909291905050508785815181106134d857fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600360008f8f8681811061352257fe5b905060200201358152602001908152602001600020600101600083838151811061354857fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff168685815181106135b057fe5b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050600360008f8f868181106135e257fe5b905060200201358152602001908152602001600020600101600083838151811061360857fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1685858151811061367057fe5b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506136a6600185615bef90919063ffffffff16565b93506136bc600182615bef90919063ffffffff16565b90506133df565b50506136d9600182615bef90919063ffffffff16565b905061331d565b50848484849850985098509850505050505092959194509250565b600061370643611a8f565b905090565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831061377c5780518252602082019150602081019050602083039250613759565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146137dc576040519150601f19603f3d011682016040523d82523d6000602084013e6137e1565b606091505b50809350819250505080613840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616d40602e913960400191505060405180910390fd5b61384b826000615aaf565b92505050919050565b61385c613193565b6138ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111613927576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180616e256030913960400191505060405180910390fd5b806004819055507f4fbe976a07a9260091c2d347f8780c4bc636392e34d5b249b367baf8a5c7ca69816040518082815260200191505060405180910390a150565b613970613193565b6139e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613a85576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b60045481565b6000806000806003600088815260200190815260200160002060010160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900460ff166002811115613bca57fe5b8160000160019054906101000a900463ffffffff168260000160059054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350935093505093509350939050565b600060036000848152602001908152602001600020600001805490509050808210613ca7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f496e64657820697320696e76616c69640000000000000000000000000000000081525060200191505060405180910390fd5b600360008481526020019081526020016000206000018281548110613cc857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614613d93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f496e64657820646f6573206e6f74206d61746368206d73672e73656e6465720081525060200191505060405180910390fd5b6000613da9600183615efe90919063ffffffff16565b9050808314613e6857600360008581526020019081526020016000206000018181548110613dd357fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360008681526020019081526020016000206000018481548110613e1f57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b6000600360008681526020019081526020016000206000018281548110613e8b57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613f0060016003600087815260200190815260200160002060000180549050615efe90919063ffffffff16565b6003600086815260200190815260200160002060000181613f219190616ca4565b5050505050565b60076020528060005260406000206000915090505481565b613f48613193565b613fba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111614013576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616cf66028913960400191505060405180910390fd5b806006819055507fc1f217a1246a98ce04e938768309107630ed86c1e0e9f9995af28e23a9c06178816040518082815260200191505060405180910390a150565b6001600260008282540192505081905550600060025490506000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411614104576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180616d1e6022913960400191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166323b872dd333061417487600760008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054615f4890919063ffffffff16565b6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561421057600080fd5b505af1158015614224573d6000803e3d6000fd5b505050506040513d602081101561423a57600080fd5b81019080805190602001909291905050506142a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180616f9a602b913960400191505060405180910390fd5b600083116142f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180616e8d602a913960400191505060405180910390fd5b600654831115614371576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f546f6f206d616e79206174746573746174696f6e73207265717565737465640081525060200191505060405180910390fd5b600060036000868152602001908152602001600020905060008160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff161480614450575061444f8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615d72565b5b806144bb57506144b98160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615fce565b155b614510576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526039815260200180616dc46039913960400191505060405180910390fd5b61451943616073565b8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff16021790555061458484616073565b8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160046101000a81548163ffffffff021916908363ffffffff160217905550828160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160086101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506146de6146d9858360010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615bef90919063ffffffff16565b616073565b8160010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16857f381545d9b1fffcb94ffbbd0bccfff9f1fb3acd474d34f7d59112a5c9973fee498686604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a350600254811461483b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b50505050565b60006060600060f873ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040518082805190602001908083835b602083106148a75780518252602082019150602081019050602083039250614884565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114614907576040519150601f19603f3d011682016040523d82523d6000602084013e61490c565b606091505b5080935081925050508061496b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806170356025913960400191505060405180910390fd5b614976826000615aaf565b9250505090565b614985613193565b6149f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111614a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180616d6e6030913960400191505060405180910390fd5b806005819055507f954fa47fa6f4e8017b99f93c73f4fbe599d786f9f5da73fe9086ab473fb455d8816040518082815260200191505060405180910390a150565b600060036000838152602001908152602001600020905060008160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff1611614b5b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260378152602001806170b26037913960400191505060405180910390fd5b614bbe8160020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16615d72565b15614c14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061708f6023913960400191505060405180910390fd5b614c1d826160da565b8060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549063ffffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550505050565b60008060006003600086815260200190815260200160002060020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff166003600087815260200190815260200160002060020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff166003600088815260200190815260200160002060020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250925092509250925092565b6000614e556003614e476002614e396002614e2b8861370b565b615f4890919063ffffffff16565b615bef90919063ffffffff16565b61689590919063ffffffff16565b9050919050565b6008602052816000526040600020602052806000526040600020600091509150505481565b60008060008714158015614e96575060008514155b614f08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310614fa25780518252602082019150602081019050602083039250614f7f565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615002576040519150601f19603f3d011682016040523d82523d6000602084013e615007565b606091505b50809250819350505081615066576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061700e6027913960400191505060405180910390fd5b615071816000615aaf565b935061507e816020615aaf565b925083839550955050505050965096945050505050565b61509d613193565b61510f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b615118816168df565b50565b615123613193565b615195576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600081116151ee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616dfd6028913960400191505060405180910390fd5b80600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff167f7cf8b633f218e9f9bc2c06107bcaddcfee6b90580863768acdcfd4f05d7af394826040518082815260200191505060405180910390a25050565b60006060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106152f557805182526020820191506020810190506020830392506152d2565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615355576040519150601f19603f3d011682016040523d82523d6000602084013e61535a565b606091505b508093508192505050806153b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806170e9602c913960400191505060405180910390fd5b6153c4826000615afe565b92505050919050565b60006153dc8533868686612567565b905060006003600087815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160059054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506154a743616073565b8260000160016101000a81548163ffffffff021916908363ffffffff16021790555060028260000160006101000a81548160ff021916908360028111156154ea57fe5b02179055508160000160056101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560006003600089815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160049054906101000a900463ffffffff160163ffffffff168160000160049054906101000a900463ffffffff1663ffffffff1610615619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d617468333220696e7465676572206f766572666c6f77000000000081525060200191505060405180910390fd5b60018160000160049054906101000a900463ffffffff16018160000160046101000a81548163ffffffff021916908363ffffffff160217905550615721600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054615bef90919063ffffffff16565b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506000600360008a815260200190815260200160002090506001600360008b815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff16141561589657806000013390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505b8473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168a7f414ff2c18c092697c4b8de49f515ac44f8bebc19b24553cf58ace913a6ac639d60405160405180910390a4505050505050505050565b600060149054906101000a900460ff161561597f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff0219169083151502179055506159a3336168df565b6159ac88613968565b6159b587613854565b6159be8661497d565b6159c785613f40565b6000848490501180156159df57508181905084849050145b615a34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061705a6035913960400191505060405180910390fd5b60008090505b84849050811015615aa457615a89858583818110615a5457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16848484818110615a7d57fe5b9050602002013561511b565b615a9d600182615bef90919063ffffffff16565b9050615a3a565b505050505050505050565b6000615abb8383615afe565b60001c905092915050565b600080828481615ad257fe5b0490506000838581615ae057fe5b061415615af05780915050615af8565b600181019150505b92915050565b60006020820183511015615b7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b600060016002811115615b9e57fe5b8260000160009054906101000a900460ff166002811115615bbb57fe5b148015615be85750615be68260000160019054906101000a900463ffffffff1663ffffffff16615d72565b155b9050919050565b600080828401905083811015615c6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4163636f756e74730000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015615d3257600080fd5b505afa158015615d46573d6000803e3d6000fd5b505050506040513d6020811015615d5c57600080fd5b8101908080519060200190929190505050905090565b6000615d9b600454836fffffffffffffffffffffffffffffffff16615bef90919063ffffffff16565b4310159050919050565b600033905090565b6060806000835111615e0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180616fe66028913960400191505060405180910390fd5b600080905060608451604051908082528060200260200182016040528015615e415781602001602082028038833980820191505090505b50905060008090505b8551811015615ebe57600060036000888481518110615e6557fe5b60200260200101518152602001908152602001600020600001805490509050808401935080838381518110615e9657fe5b60200260200101818152505050615eb7600182615bef90919063ffffffff16565b9050615e4a565b508082604051908082528060200260200182016040528015615eef5781602001602082028038833980820191505090505b50809050935093505050915091565b6000615f4083836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250616a23565b905092915050565b600080831415615f5b5760009050615fc8565b6000828402905082848281615f6c57fe5b0414615fc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180616fc56021913960400191505060405180910390fd5b809150505b92915050565b600061606a615fdb616ae3565b73ffffffffffffffffffffffffffffffffffffffff1663e45def956040518163ffffffff1660e01b815260040160206040518083038186803b15801561602057600080fd5b505afa158015616034573d6000803e3d6000fd5b505050506040513d602081101561604a57600080fd5b810190808051906020019092919050505083615bef90919063ffffffff16565b43109050919050565b600064010000000082106160d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806171466026913960400191505060405180910390fd5b819050919050565b60006003600083815260200190815260200160002060010160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060006003600084815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000616192616ae3565b73ffffffffffffffffffffffffffffffffffffffff1663fc4847266161dc6005548560000160009054906101000a900463ffffffff1663ffffffff16615bef90919063ffffffff16565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561621057600080fd5b505afa158015616224573d6000803e3d6000fd5b505050506040513d602081101561623a57600080fd5b810190808051906020019092919050505090506000616257615c77565b90506000616263612e89565b90506060816040519080825280602002602001820160405280156162965781602001602082028038833980820191505090505b50905060008090505b828110156162cd57808282815181106162b457fe5b602002602001018181525050808060010191505061629f565b50818560000160049054906101000a900463ffffffff1663ffffffff16111561635e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6e6f7420656e6f7567682069737375657273000000000000000000000000000081525060200191505060405180910390fd5b60008090505b8560000160049054906101000a900463ffffffff1663ffffffff1681101561688b57600083116163fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6e6f7420656e6f7567682069737375657273000000000000000000000000000081525060200191505060405180910390fd5b84604051602001808281526020019150506040516020818303038152906040528051906020012094506000838660001c8161643357fe5b069050600061645484838151811061644757fe5b6020026020010151611772565b905060008673ffffffffffffffffffffffffffffffffffffffff166393c5c487836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156164d557600080fd5b505afa1580156164e9573d6000803e3d6000fd5b505050506040513d60208110156164ff57600080fd5b8101908080519060200190929190505050905060008a60020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600281111561656457fe5b8160000160009054906101000a900460ff16600281111561658157fe5b14801561664257508773ffffffffffffffffffffffffffffffffffffffff1663c2e0ee20836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561660657600080fd5b505afa15801561661a573d6000803e3d6000fd5b505050506040513d602081101561663057600080fd5b81019080805190602001909291905050505b156168405761665b600186615bef90919063ffffffff16565b945060018160000160006101000a81548160ff0219169083600281111561667e57fe5b02179055508960000160009054906101000a900463ffffffff168160000160016101000a81548163ffffffff021916908363ffffffff1602179055508960000160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160000160056101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a6001018290806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168d7faf7f470b643316cf44c1f2898328a075e7602945b4f8584f48ba4ad2d8a2ea9d8d60000160089054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a45b616854600188615efe90919063ffffffff16565b965085878151811061686257fe5b602002602001015186858151811061687657fe5b60200260200101818152505050505050616364565b5050505050505050565b60006168d783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250616bde565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415616965576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180616d9e6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000838311158290616ad0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015616a95578082015181840152602081019050616a7a565b50505050905090810190601f168015616ac25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f52616e646f6d00000000000000000000000000000000000000000000000000008152506006019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015616b9e57600080fd5b505afa158015616bb2573d6000803e3d6000fd5b505050506040513d6020811015616bc857600080fd5b8101908080519060200190929190505050905090565b60008083118290616c8a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015616c4f578082015181840152602081019050616c34565b50505050905090810190601f168015616c7c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581616c9657fe5b049050809150509392505050565b815481835581811115616ccb57818360005260206000209182019101616cca9190616cd0565b5b505050565b616cf291905b80821115616cee576000816000905550600101616cd6565b5090565b9056fe6d61784174746573746174696f6e732068617320746f2062652067726561746572207468616e2030496e76616c6964206174746573746174696f6e52657175657374466565546f6b656e6572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c6573656c6563744973737565727357616974426c6f636b732068617320746f2062652067726561746572207468616e20304f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737354686572652065786973747320616e20756e657870697265642c20756e73656c6563746564206174746573746174696f6e2072657175657374596f75206861766520746f20737065636966792061206665652067726561746572207468616e20306174746573746174696f6e457870697279426c6f636b732068617320746f2062652067726561746572207468616e20306572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c65596f75206861766520746f2072657175657374206174206c656173742031206174746573746174696f6e6572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c654174746573746174696f6e20636f646520646f6573206e6f74206d6174636820616e79206f75747374616e64696e67206174746573746174696f6e6572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c655472616e73666572206f66206174746573746174696f6e20726571756573742066656573206661696c6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77596f75206861766520746f2070617373206174206c65617374206f6e65206964656e7469666965726572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c656572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c656174746573746174696f6e52657175657374466565546f6b656e732073706563696669636174696f6e2077617320696e76616c6964546865206174746573746174696f6e20726571756573742068617320657870697265644e6f20756e73656c6563746564206174746573746174696f6e207265717565737420746f2073656c656374206973737565727320666f726572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c6553616665436173743a2076616c756520646f65736e27742066697420696e20333220626974736572726f722063616c6c696e67206861736848656164657220707265636f6d70696c65a165627a7a723058201ef00b4875bbe399c297607d5f84c5130ccff4db50536ec1730a190a9ed9dba90029

External libraries