Address Details
contract

0x5220d91403aa39d25De79699dCa75Ee722E68102

Contract Name
Accounts
Creator
0x0cc59e–f1502d at 0xed2a54–11ee8d
Balance
0 CELO
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
2157652
Contract name:
Accounts




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




Verified at
2020-08-11T18:43:49.406394Z

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  function setAttestationExpiryBlocks(uint256) external;

  function getMaxAttestations() external view returns (uint256);

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

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

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

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

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

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

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

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

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

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

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

  IRegistry public registry;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

contract ReentrancyGuard {
  
  uint256 private _guardCounter;

  constructor() internal {
    
    
    _guardCounter = 1;
  }

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

contract Accounts is IAccounts, Ownable, ReentrancyGuard, Initializable, UsingRegistry {
  using SafeMath for uint256;

  struct Signers {
    
    
    address vote;
    
    
    
    
    address validator;
    
    
    address attestation;
  }

  struct Account {
    bool exists;
    
    
    
    Signers signers;
    
    
    address walletAddress;
    
    string name;
    
    bytes dataEncryptionKey;
    
    string metadataURL;
  }

  mapping(address => Account) private accounts;
  
  mapping(address => address) public authorizedBy;

  event AttestationSignerAuthorized(address indexed account, address signer);
  event VoteSignerAuthorized(address indexed account, address signer);
  event ValidatorSignerAuthorized(address indexed account, address signer);
  event AttestationSignerRemoved(address indexed account, address oldSigner);
  event VoteSignerRemoved(address indexed account, address oldSigner);
  event ValidatorSignerRemoved(address indexed account, address oldSigner);
  event AccountDataEncryptionKeySet(address indexed account, bytes dataEncryptionKey);
  event AccountNameSet(address indexed account, string name);
  event AccountMetadataURLSet(address indexed account, string metadataURL);
  event AccountWalletAddressSet(address indexed account, address walletAddress);
  event AccountCreated(address indexed account);

  
  function initialize(address registryAddress) external initializer {
    _transferOwnership(msg.sender);
    setRegistry(registryAddress);
  }

  
  function setAccount(
    string calldata name,
    bytes calldata dataEncryptionKey,
    address walletAddress,
    uint8 v,
    bytes32 r,
    bytes32 s
  ) external {
    if (!isAccount(msg.sender)) {
      createAccount();
    }
    setName(name);
    setAccountDataEncryptionKey(dataEncryptionKey);
    setWalletAddress(walletAddress, v, r, s);
  }

  
  function createAccount() public returns (bool) {
    require(isNotAccount(msg.sender) && isNotAuthorizedSigner(msg.sender), "Account exists");
    Account storage account = accounts[msg.sender];
    account.exists = true;
    emit AccountCreated(msg.sender);
    return true;
  }

  
  function setName(string memory name) public {
    require(isAccount(msg.sender), "Unknown account");
    Account storage account = accounts[msg.sender];
    account.name = name;
    emit AccountNameSet(msg.sender, name);
  }

  
  function setWalletAddress(address walletAddress, uint8 v, bytes32 r, bytes32 s) public {
    require(isAccount(msg.sender), "Unknown account");
    if (!(walletAddress == msg.sender || walletAddress == address(0x0))) {
      address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s);
      require(signer == walletAddress, "Invalid signature");
    }
    Account storage account = accounts[msg.sender];
    account.walletAddress = walletAddress;
    emit AccountWalletAddressSet(msg.sender, walletAddress);
  }

  
  function setAccountDataEncryptionKey(bytes memory dataEncryptionKey) public {
    require(dataEncryptionKey.length >= 33, "data encryption key length <= 32");
    Account storage account = accounts[msg.sender];
    account.dataEncryptionKey = dataEncryptionKey;
    emit AccountDataEncryptionKeySet(msg.sender, dataEncryptionKey);
  }

  
  function setMetadataURL(string calldata metadataURL) external {
    require(isAccount(msg.sender), "Unknown account");
    Account storage account = accounts[msg.sender];
    account.metadataURL = metadataURL;
    emit AccountMetadataURLSet(msg.sender, metadataURL);
  }

  
  function authorizeVoteSigner(address signer, uint8 v, bytes32 r, bytes32 s)
    external
    nonReentrant
  {
    Account storage account = accounts[msg.sender];
    authorize(signer, v, r, s);
    account.signers.vote = signer;
    emit VoteSignerAuthorized(msg.sender, signer);
  }

  
  function authorizeValidatorSigner(address signer, uint8 v, bytes32 r, bytes32 s)
    external
    nonReentrant
  {
    Account storage account = accounts[msg.sender];
    authorize(signer, v, r, s);
    account.signers.validator = signer;
    require(!getValidators().isValidator(msg.sender), "Cannot authorize validator signer");
    emit ValidatorSignerAuthorized(msg.sender, signer);
  }

  
  function authorizeValidatorSignerWithPublicKey(
    address signer,
    uint8 v,
    bytes32 r,
    bytes32 s,
    bytes calldata ecdsaPublicKey
  ) external nonReentrant {
    Account storage account = accounts[msg.sender];
    authorize(signer, v, r, s);
    account.signers.validator = signer;
    require(
      getValidators().updateEcdsaPublicKey(msg.sender, signer, ecdsaPublicKey),
      "Failed to update ECDSA public key"
    );
    emit ValidatorSignerAuthorized(msg.sender, signer);
  }

  
  function authorizeValidatorSignerWithKeys(
    address signer,
    uint8 v,
    bytes32 r,
    bytes32 s,
    bytes calldata ecdsaPublicKey,
    bytes calldata blsPublicKey,
    bytes calldata blsPop
  ) external nonReentrant {
    Account storage account = accounts[msg.sender];
    authorize(signer, v, r, s);
    account.signers.validator = signer;
    require(
      getValidators().updatePublicKeys(msg.sender, signer, ecdsaPublicKey, blsPublicKey, blsPop),
      "Failed to update validator keys"
    );
    emit ValidatorSignerAuthorized(msg.sender, signer);
  }

  
  function authorizeAttestationSigner(address signer, uint8 v, bytes32 r, bytes32 s) public {
    Account storage account = accounts[msg.sender];
    authorize(signer, v, r, s);
    account.signers.attestation = signer;
    emit AttestationSignerAuthorized(msg.sender, signer);
  }

  
  function removeVoteSigner() public {
    Account storage account = accounts[msg.sender];
    emit VoteSignerRemoved(msg.sender, account.signers.vote);
    account.signers.vote = address(0);
  }

  
  function removeValidatorSigner() public {
    Account storage account = accounts[msg.sender];
    emit ValidatorSignerRemoved(msg.sender, account.signers.validator);
    account.signers.validator = address(0);
  }

  
  function removeAttestationSigner() public {
    Account storage account = accounts[msg.sender];
    emit AttestationSignerRemoved(msg.sender, account.signers.attestation);
    account.signers.attestation = address(0);
  }

  
  function attestationSignerToAccount(address signer) external view returns (address) {
    address authorizingAccount = authorizedBy[signer];
    if (authorizingAccount != address(0)) {
      require(
        accounts[authorizingAccount].signers.attestation == signer,
        "not active authorized attestation signer"
      );
      return authorizingAccount;
    } else {
      require(isAccount(signer), "not an account");
      return signer;
    }
  }

  
  function validatorSignerToAccount(address signer) public view returns (address) {
    address authorizingAccount = authorizedBy[signer];
    if (authorizingAccount != address(0)) {
      require(
        accounts[authorizingAccount].signers.validator == signer,
        "not active authorized validator signer"
      );
      return authorizingAccount;
    } else {
      require(isAccount(signer), "not an account");
      return signer;
    }
  }

  
  function voteSignerToAccount(address signer) external view returns (address) {
    address authorizingAccount = authorizedBy[signer];
    if (authorizingAccount != address(0)) {
      require(
        accounts[authorizingAccount].signers.vote == signer,
        "not active authorized vote signer"
      );
      return authorizingAccount;
    } else {
      require(isAccount(signer), "not an account");
      return signer;
    }
  }

  
  function signerToAccount(address signer) external view returns (address) {
    address authorizingAccount = authorizedBy[signer];
    if (authorizingAccount != address(0)) {
      return authorizingAccount;
    } else {
      require(isAccount(signer), "Not an account");
      return signer;
    }
  }

  
  function getVoteSigner(address account) public view returns (address) {
    require(isAccount(account), "Unknown account");
    address signer = accounts[account].signers.vote;
    return signer == address(0) ? account : signer;
  }

  
  function getValidatorSigner(address account) public view returns (address) {
    require(isAccount(account), "Unknown account");
    address signer = accounts[account].signers.validator;
    return signer == address(0) ? account : signer;
  }

  
  function getAttestationSigner(address account) public view returns (address) {
    require(isAccount(account), "Unknown account");
    address signer = accounts[account].signers.attestation;
    return signer == address(0) ? account : signer;
  }

  
  function hasAuthorizedVoteSigner(address account) external view returns (bool) {
    require(isAccount(account));
    address signer = accounts[account].signers.vote;
    return signer != address(0);
  }

  
  function hasAuthorizedValidatorSigner(address account) external view returns (bool) {
    require(isAccount(account));
    address signer = accounts[account].signers.validator;
    return signer != address(0);
  }

  
  function hasAuthorizedAttestationSigner(address account) external view returns (bool) {
    require(isAccount(account));
    address signer = accounts[account].signers.attestation;
    return signer != address(0);
  }

  
  function getName(address account) external view returns (string memory) {
    return accounts[account].name;
  }

  
  function getMetadataURL(address account) external view returns (string memory) {
    return accounts[account].metadataURL;
  }

  
  function batchGetMetadataURL(address[] calldata accountsToQuery)
    external
    view
    returns (uint256[] memory, bytes memory)
  {
    uint256 totalSize = 0;
    uint256[] memory sizes = new uint256[](accountsToQuery.length);
    for (uint256 i = 0; i < accountsToQuery.length; i = i.add(1)) {
      sizes[i] = bytes(accounts[accountsToQuery[i]].metadataURL).length;
      totalSize = totalSize.add(sizes[i]);
    }

    bytes memory data = new bytes(totalSize);
    uint256 pointer = 0;
    for (uint256 i = 0; i < accountsToQuery.length; i = i.add(1)) {
      for (uint256 j = 0; j < sizes[i]; j = j.add(1)) {
        data[pointer] = bytes(accounts[accountsToQuery[i]].metadataURL)[j];
        pointer = pointer.add(1);
      }
    }
    return (sizes, data);
  }

  
  function getDataEncryptionKey(address account) external view returns (bytes memory) {
    return accounts[account].dataEncryptionKey;
  }

  
  function getWalletAddress(address account) external view returns (address) {
    return accounts[account].walletAddress;
  }

  
  function isAccount(address account) public view returns (bool) {
    return (accounts[account].exists);
  }

  
  function isNotAccount(address account) internal view returns (bool) {
    return (!accounts[account].exists);
  }

  
  function isAuthorizedSigner(address signer) external view returns (bool) {
    return (authorizedBy[signer] != address(0));
  }

  
  function isNotAuthorizedSigner(address signer) internal view returns (bool) {
    return (authorizedBy[signer] == address(0));
  }

  
  function authorize(address authorized, uint8 v, bytes32 r, bytes32 s) private {
    require(isAccount(msg.sender), "Unknown account");
    require(
      isNotAccount(authorized) && isNotAuthorizedSigner(authorized),
      "Cannot re-authorize address or locked gold account."
    );

    address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s);
    require(signer == authorized, "Invalid signature");

    authorizedBy[authorized] = msg.sender;
  }
}
        

Contract ABI

[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"hasAuthorizedValidatorSigner","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"authorizeValidatorSignerWithPublicKey","inputs":[{"type":"address","name":"signer"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"},{"type":"bytes","name":"ecdsaPublicKey"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setAccountDataEncryptionKey","inputs":[{"type":"bytes","name":"dataEncryptionKey"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeVoteSigner","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"authorizeValidatorSignerWithKeys","inputs":[{"type":"address","name":"signer"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"},{"type":"bytes","name":"ecdsaPublicKey"},{"type":"bytes","name":"blsPublicKey"},{"type":"bytes","name":"blsPop"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"initialized","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"getWalletAddress","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isAccount","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"getVoteSigner","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"authorizeVoteSigner","inputs":[{"type":"address","name":"signer"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isAuthorizedSigner","inputs":[{"type":"address","name":"signer"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"getValidatorSigner","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":""}],"name":"getName","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"hasAuthorizedVoteSigner","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"getAttestationSigner","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"validatorSignerToAccount","inputs":[{"type":"address","name":"signer"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"voteSignerToAccount","inputs":[{"type":"address","name":"signer"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMetadataURL","inputs":[{"type":"string","name":"metadataURL"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeAttestationSigner","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"authorizeAttestationSigner","inputs":[{"type":"address","name":"signer"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"registry","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"attestationSignerToAccount","inputs":[{"type":"address","name":"signer"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":""},{"type":"bytes","name":""}],"name":"batchGetMetadataURL","inputs":[{"type":"address[]","name":"accountsToQuery"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setAccount","inputs":[{"type":"string","name":"name"},{"type":"bytes","name":"dataEncryptionKey"},{"type":"address","name":"walletAddress"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"signerToAccount","inputs":[{"type":"address","name":"signer"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setWalletAddress","inputs":[{"type":"address","name":"walletAddress"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"createAccount","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeValidatorSigner","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":""}],"name":"getMetadataURL","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRegistry","inputs":[{"type":"address","name":"registryAddress"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes","name":""}],"name":"getDataEncryptionKey","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"authorizedBy","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"authorizeValidatorSigner","inputs":[{"type":"address","name":"signer"},{"type":"uint8","name":"v"},{"type":"bytes32","name":"r"},{"type":"bytes32","name":"s"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"hasAuthorizedAttestationSigner","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setName","inputs":[{"type":"string","name":"name"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"registryAddress"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner"}],"constant":false},{"type":"event","name":"AttestationSignerAuthorized","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"signer","indexed":false}],"anonymous":false},{"type":"event","name":"VoteSignerAuthorized","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"signer","indexed":false}],"anonymous":false},{"type":"event","name":"ValidatorSignerAuthorized","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"signer","indexed":false}],"anonymous":false},{"type":"event","name":"AttestationSignerRemoved","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"oldSigner","indexed":false}],"anonymous":false},{"type":"event","name":"VoteSignerRemoved","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"oldSigner","indexed":false}],"anonymous":false},{"type":"event","name":"ValidatorSignerRemoved","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"oldSigner","indexed":false}],"anonymous":false},{"type":"event","name":"AccountDataEncryptionKeySet","inputs":[{"type":"address","name":"account","indexed":true},{"type":"bytes","name":"dataEncryptionKey","indexed":false}],"anonymous":false},{"type":"event","name":"AccountNameSet","inputs":[{"type":"address","name":"account","indexed":true},{"type":"string","name":"name","indexed":false}],"anonymous":false},{"type":"event","name":"AccountMetadataURLSet","inputs":[{"type":"address","name":"account","indexed":true},{"type":"string","name":"metadataURL","indexed":false}],"anonymous":false},{"type":"event","name":"AccountWalletAddressSet","inputs":[{"type":"address","name":"account","indexed":true},{"type":"address","name":"walletAddress","indexed":false}],"anonymous":false},{"type":"event","name":"AccountCreated","inputs":[{"type":"address","name":"account","indexed":true}],"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

0x6080604052600062000016620000c160201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35060018081905550620000c9565b600033905090565b61510080620000d96000396000f3fe608060405234801561001057600080fd5b50600436106102485760003560e01c806376afa04c1161013b578063a5ec94f9116100b8578063baf7ef0f1161007c578063baf7ef0f146112c8578063c2e0ee201461132d578063c47f002714611389578063c4d66de814611444578063f2fde38b1461148857610248565b8063a5ec94f91461107c578063a8ae1a3d14611086578063a91ee0dc14611143578063ae32fa0e14611187578063b5a664c21461124457610248565b80638f32d59b116100ff5780638f32d59b14610e4057806390b12b4714610e6257806393c5c48714610f715780639cafb2a114610ff55780639dca362f1461105a57610248565b806376afa04c14610b895780637b10399914610bee5780637b2434cb14610c385780638adaf96f14610cbc5780638da5cb5b14610df657610248565b806349045e16116101c957806364439b431161018d57806364439b43146109f45780636642d59414610a78578063715018a614610afc578063747daec514610b06578063760fbbb214610b7f57610248565b806349045e16146107775780634ce38b5f146107d35780635fd4b08a14610857578063614ed4931461091457806361bab1ae1461097057610248565b8063158ef93e11610210578063158ef93e1461058c5780631fd9afa5146105ae57806325ca4c9c1461063257806341ddd8801461068e5780634282ee6d1461071257610248565b80630127dbed1461024d5780630fa750d2146102a95780630fe7abab1461036357806310c504b51461041e5780631465b92314610428575b600080fd5b61028f6004803603602081101561026357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114cc565b604051808215151515815260200191505060405180910390f35b610361600480360360a08110156102bf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561031d57600080fd5b82018360208201111561032f57600080fd5b8035906020019184600183028401116401000000008311171561035157600080fd5b9091929391929390505050611583565b005b61041c6004803603602081101561037957600080fd5b810190808035906020019064010000000081111561039657600080fd5b8201836020820111156103a857600080fd5b803590602001918460018302840111640100000000831117156103ca57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506118a8565b005b610426611a33565b005b61058a600480360360e081101561043e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561049c57600080fd5b8201836020820111156104ae57600080fd5b803590602001918460018302840111640100000000831117156104d057600080fd5b9091929391929390803590602001906401000000008111156104f157600080fd5b82018360208201111561050357600080fd5b8035906020019184600183028401116401000000008311171561052557600080fd5b90919293919293908035906020019064010000000081111561054657600080fd5b82018360208201111561055857600080fd5b8035906020019184600183028401116401000000008311171561057a57600080fd5b9091929391929390505050611b61565b005b610594611f0f565b604051808215151515815260200191505060405180910390f35b6105f0600480360360208110156105c457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f22565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106746004803603602081101561064857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f8e565b604051808215151515815260200191505060405180910390f35b6106d0600480360360208110156106a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611fe7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107756004803603608081101561072857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612112565b005b6107b96004803603602081101561078d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506122b7565b604051808215151515815260200191505060405180910390f35b610815600480360360208110156107e957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061234f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6108996004803603602081101561086d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061247a565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108d95780820151818401526020810190506108be565b50505050905090810190601f1680156109065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6109566004803603602081101561092a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061255e565b604051808215151515815260200191505060405180910390f35b6109b26004803603602081101561098657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612615565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a3660048036036020811015610a0a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612740565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610aba60048036036020811015610a8e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612950565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610b04612b60565b005b610b7d60048036036020811015610b1c57600080fd5b8101908080359060200190640100000000811115610b3957600080fd5b820183602082011115610b4b57600080fd5b80359060200191846001830284011164010000000083111715610b6d57600080fd5b9091929391929390505050612c99565b005b610b87612dea565b005b610bec60048036036080811015610b9f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612f18565b005b610bf661302e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c7a60048036036020811015610c4e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613054565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610d3360048036036020811015610cd257600080fd5b8101908080359060200190640100000000811115610cef57600080fd5b820183602082011115610d0157600080fd5b80359060200191846020830284011164010000000083111715610d2357600080fd5b9091929391929390505050613264565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610d7a578082015181840152602081019050610d5f565b50505050905001838103825284818151815260200191508051906020019080838360005b83811015610db9578082015181840152602081019050610d9e565b50505050905090810190601f168015610de65780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b610dfe613563565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610e4861358c565b604051808215151515815260200191505060405180910390f35b610f6f600480360360c0811015610e7857600080fd5b8101908080359060200190640100000000811115610e9557600080fd5b820183602082011115610ea757600080fd5b80359060200191846001830284011164010000000083111715610ec957600080fd5b909192939192939080359060200190640100000000811115610eea57600080fd5b820183602082011115610efc57600080fd5b80359060200191846001830284011164010000000083111715610f1e57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506135ea565b005b610fb360048036036020811015610f8757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506136b1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110586004803603608081101561100b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506137d8565b005b611062613b3f565b604051808215151515815260200191505060405180910390f35b611084613c78565b005b6110c86004803603602081101561109c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613da6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156111085780820151818401526020810190506110ed565b50505050905090810190601f1680156111355780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6111856004803603602081101561115957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613e8a565b005b6111c96004803603602081101561119d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061402e565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156112095780820151818401526020810190506111ee565b50505050905090810190601f1680156112365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6112866004803603602081101561125a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614112565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61132b600480360360808110156112de57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614145565b005b61136f6004803603602081101561134357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506143ff565b604051808215151515815260200191505060405180910390f35b6114426004803603602081101561139f57600080fd5b81019080803590602001906401000000008111156113bc57600080fd5b8201836020820111156113ce57600080fd5b803590602001918460018302840111640100000000831117156113f057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506144b6565b005b6114866004803603602081101561145a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614644565b005b6114ca6004803603602081101561149e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506146f7565b005b60006114d782611f8e565b6114e057600080fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506115e98888888861477d565b878160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611637614a65565b73ffffffffffffffffffffffffffffffffffffffff16634e06fd8a338a87876040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b15801561171d57600080fd5b505af1158015611731573d6000803e3d6000fd5b505050506040513d602081101561174757600080fd5b81019080805190602001909291905050506117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806150936021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494389604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250600154811461189f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b50505050505050565b602181511015611920576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6461746120656e6372797074696f6e206b6579206c656e677468203c3d20333281525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508181600601908051906020019061197b929190614e25565b503373ffffffffffffffffffffffffffffffffffffffff167f43fdefe0a824cb0e3bbaf9c4bc97669187996136fe9282382baf10787f0d808d836040518080602001828103825283818151815260200191508051906020019080838360005b838110156119f55780820151818401526020810190506119da565b50505050905090810190601f168015611a225780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff167fa197481f404d8a8082368ad7445380f01e75f27dea6b7aef234a4ce071127fae8260010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260008160010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611bc78c8c8c8c61477d565b8b8160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611c15614a65565b73ffffffffffffffffffffffffffffffffffffffff1663713ea0f3338e8b8b8b8b8b8b6040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018060200184810384528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508481038352888882818152602001925080828437600081840152601f19601f8201169050808301925050508481038252868682818152602001925080828437600081840152601f19601f8201169050808301925050509b505050505050505050505050602060405180830381600087803b158015611d6357600080fd5b505af1158015611d77573d6000803e3d6000fd5b505050506040513d6020811015611d8d57600080fd5b8101908080519060200190929190505050611e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4661696c656420746f207570646174652076616c696461746f72206b6579730081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf949438d604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2506001548114611f02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050505050505050565b600260009054906101000a900460ff1681565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b6000611ff282611f8e565b612064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612108578061210a565b825b915050919050565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506121788686868661477d565b858160010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167faab5f8a189373aaa290f42ae65ea5d7971b732366ca5bf66556e76263944af2887604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25060015481146122b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600061235a82611f8e565b6123cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146124705780612472565b825b915050919050565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156125525780601f1061252757610100808354040283529160200191612552565b820191906000526020600020905b81548152906001019060200180831161253557829003601f168201915b50505050509050919050565b600061256982611f8e565b61257257600080fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600061262082611f8e565b612692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146127365780612738565b825b915050919050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146128cb578273ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146128c2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614fcb6026913960400191505060405180910390fd5b8091505061294b565b6128d483611f8e565b612946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612adb578273ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ad2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806150b46021913960400191505060405180910390fd5b80915050612b5b565b612ae483611f8e565b612b56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b612b6861358c565b612bda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b612ca233611f8e565b612d14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508282826007019190612d6a929190614ea5565b503373ffffffffffffffffffffffffffffffffffffffff167f0b5629fec5b6b5a1c2cfe0de7495111627a8cf297dced72e0669527425d3f01b848460405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff167f14670729407debb6ed03d885f8ba57155de89ce39bf17127ae4900ec7c2ad1038260010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260008160010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050612f678585858561477d565b848160010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f9dfbc5a621c3e2d0d83beee687a17dfc796bbce2118793e5e254409bb265ca0b86604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050505050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146131df578273ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806150176028913960400191505060405180910390fd5b8091505061325f565b6131e883611f8e565b61325a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b60608060008090506060858590506040519080825280602002602001820160405280156132a05781602001602082028038833980820191505090505b50905060008090505b8686905081101561338e57600360008888848181106132c457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070180546001816001161561010002031660029004905082828151811061333f57fe5b60200260200101818152505061337182828151811061335a57fe5b602002602001015184614b6090919063ffffffff16565b9250613387600182614b6090919063ffffffff16565b90506132a9565b506060826040519080825280601f01601f1916602001820160405280156133c45781602001600182028038833980820191505090505b509050600080905060008090505b888890508110156135515760008090505b8482815181106133ef57fe5b602002602001015181101561353557600360008b8b8581811061340e57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018181546001816001161561010002031660029004811061348457fe5b8154600116156134a35790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000028484815181106134d557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613518600184614b6090919063ffffffff16565b925061352e600182614b6090919063ffffffff16565b90506133e3565b5061354a600182614b6090919063ffffffff16565b90506133d2565b50828295509550505050509250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166135ce614be8565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6135f333611f8e565b613601576135ff613b3f565b505b61364e88888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506144b6565b61369b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506118a8565b6136a7848484846137d8565b5050505050505050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461375357809150506137d3565b61375c83611f8e565b6137ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b6137e133611f8e565b613853576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806138b95750600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b613a3857600073415406e7b0b8a511f4e9111c34793cb0b465f8e36396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561395857600080fd5b505af415801561396c573d6000803e3d6000fd5b505050506040513d602081101561398257600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613a36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b505b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050848160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167ff81d74398fd47e35c36b714019df15f200f623dde569b5b531d6a0b4da5c5f2686604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050505050565b6000613b4a33614bf0565b8015613b5b5750613b5a33614c4a565b5b613bcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4163636f756e742065786973747300000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167f805996f252884581e2f74cf3d2b03564d5ec26ccc90850ae12653dc1b72d1fa260405160405180910390a2600191505090565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff167fa54764c62865ff0cd3f271fb1d4635662bff10f0878694f1654fb7fbdecb830d8260010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260008160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613e7e5780601f10613e5357610100808354040283529160200191613e7e565b820191906000526020600020905b815481529060010190602001808311613e6157829003601f168201915b50505050509050919050565b613e9261358c565b613f04576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613fa7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156141065780601f106140db57610100808354040283529160200191614106565b820191906000526020600020905b8154815290600101906020018083116140e957829003601f168201915b50505050509050919050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506141ab8686868661477d565b858160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506141f9614a65565b73ffffffffffffffffffffffffffffffffffffffff1663facd743b336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561427557600080fd5b505afa158015614289573d6000803e3d6000fd5b505050506040513d602081101561429f57600080fd5b810190808051906020019092919050505015614306576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061503f6021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494387604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25060015481146143f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b600061440a82611f8e565b61441357600080fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b6144bf33611f8e565b614531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508181600501908051906020019061458c929190614f25565b503373ffffffffffffffffffffffffffffffffffffffff167fa6e2c5a23bb917ba0a584c4b250257ddad698685829b66a8813c004b39934fe4836040518080602001828103825283818151815260200191508051906020019080838360005b838110156146065780820151818401526020810190506145eb565b50505050905090810190601f1680156146335780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b600260009054906101000a900460ff16156146c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600260006101000a81548160ff0219169083151502179055506146eb33614ce1565b6146f481613e8a565b50565b6146ff61358c565b614771576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61477a81614ce1565b50565b61478633611f8e565b6147f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b61480184614bf0565b8015614812575061481184614c4a565b5b614867576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806150606033913960400191505060405180910390fd5b600073415406e7b0b8a511f4e9111c34793cb0b465f8e36396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561490257600080fd5b505af4158015614916573d6000803e3d6000fd5b505050506040513d602081101561492c57600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146149e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b33600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b6000600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f56616c696461746f727300000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614b2057600080fd5b505afa158015614b34573d6000803e3d6000fd5b505050506040513d6020811015614b4a57600080fd5b8101908080519060200190929190505050905090565b600080828401905083811015614bde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600033905090565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16159050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614d67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614ff16026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614e6657805160ff1916838001178555614e94565b82800160010185558215614e94579182015b82811115614e93578251825591602001919060010190614e78565b5b509050614ea19190614fa5565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614ee657803560ff1916838001178555614f14565b82800160010185558215614f14579182015b82811115614f13578235825591602001919060010190614ef8565b5b509050614f219190614fa5565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614f6657805160ff1916838001178555614f94565b82800160010185558215614f94579182015b82811115614f93578251825591602001919060010190614f78565b5b509050614fa19190614fa5565b5090565b614fc791905b80821115614fc3576000816000905550600101614fab565b5090565b9056fe6e6f742061637469766520617574686f72697a65642076616c696461746f72207369676e65724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573736e6f742061637469766520617574686f72697a6564206174746573746174696f6e207369676e657243616e6e6f7420617574686f72697a652076616c696461746f72207369676e657243616e6e6f742072652d617574686f72697a652061646472657373206f72206c6f636b656420676f6c64206163636f756e742e4661696c656420746f20757064617465204543445341207075626c6963206b65796e6f742061637469766520617574686f72697a656420766f7465207369676e6572a165627a7a72305820baa23b4cb7dd921c21f9fcbdaccd486b4e34561057b53adc4c1488eb0f021c660029

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106102485760003560e01c806376afa04c1161013b578063a5ec94f9116100b8578063baf7ef0f1161007c578063baf7ef0f146112c8578063c2e0ee201461132d578063c47f002714611389578063c4d66de814611444578063f2fde38b1461148857610248565b8063a5ec94f91461107c578063a8ae1a3d14611086578063a91ee0dc14611143578063ae32fa0e14611187578063b5a664c21461124457610248565b80638f32d59b116100ff5780638f32d59b14610e4057806390b12b4714610e6257806393c5c48714610f715780639cafb2a114610ff55780639dca362f1461105a57610248565b806376afa04c14610b895780637b10399914610bee5780637b2434cb14610c385780638adaf96f14610cbc5780638da5cb5b14610df657610248565b806349045e16116101c957806364439b431161018d57806364439b43146109f45780636642d59414610a78578063715018a614610afc578063747daec514610b06578063760fbbb214610b7f57610248565b806349045e16146107775780634ce38b5f146107d35780635fd4b08a14610857578063614ed4931461091457806361bab1ae1461097057610248565b8063158ef93e11610210578063158ef93e1461058c5780631fd9afa5146105ae57806325ca4c9c1461063257806341ddd8801461068e5780634282ee6d1461071257610248565b80630127dbed1461024d5780630fa750d2146102a95780630fe7abab1461036357806310c504b51461041e5780631465b92314610428575b600080fd5b61028f6004803603602081101561026357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114cc565b604051808215151515815260200191505060405180910390f35b610361600480360360a08110156102bf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561031d57600080fd5b82018360208201111561032f57600080fd5b8035906020019184600183028401116401000000008311171561035157600080fd5b9091929391929390505050611583565b005b61041c6004803603602081101561037957600080fd5b810190808035906020019064010000000081111561039657600080fd5b8201836020820111156103a857600080fd5b803590602001918460018302840111640100000000831117156103ca57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506118a8565b005b610426611a33565b005b61058a600480360360e081101561043e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561049c57600080fd5b8201836020820111156104ae57600080fd5b803590602001918460018302840111640100000000831117156104d057600080fd5b9091929391929390803590602001906401000000008111156104f157600080fd5b82018360208201111561050357600080fd5b8035906020019184600183028401116401000000008311171561052557600080fd5b90919293919293908035906020019064010000000081111561054657600080fd5b82018360208201111561055857600080fd5b8035906020019184600183028401116401000000008311171561057a57600080fd5b9091929391929390505050611b61565b005b610594611f0f565b604051808215151515815260200191505060405180910390f35b6105f0600480360360208110156105c457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f22565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6106746004803603602081101561064857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f8e565b604051808215151515815260200191505060405180910390f35b6106d0600480360360208110156106a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611fe7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6107756004803603608081101561072857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612112565b005b6107b96004803603602081101561078d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506122b7565b604051808215151515815260200191505060405180910390f35b610815600480360360208110156107e957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061234f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6108996004803603602081101561086d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061247a565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108d95780820151818401526020810190506108be565b50505050905090810190601f1680156109065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6109566004803603602081101561092a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061255e565b604051808215151515815260200191505060405180910390f35b6109b26004803603602081101561098657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612615565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a3660048036036020811015610a0a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612740565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610aba60048036036020811015610a8e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612950565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610b04612b60565b005b610b7d60048036036020811015610b1c57600080fd5b8101908080359060200190640100000000811115610b3957600080fd5b820183602082011115610b4b57600080fd5b80359060200191846001830284011164010000000083111715610b6d57600080fd5b9091929391929390505050612c99565b005b610b87612dea565b005b610bec60048036036080811015610b9f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612f18565b005b610bf661302e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610c7a60048036036020811015610c4e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613054565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610d3360048036036020811015610cd257600080fd5b8101908080359060200190640100000000811115610cef57600080fd5b820183602082011115610d0157600080fd5b80359060200191846020830284011164010000000083111715610d2357600080fd5b9091929391929390505050613264565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b83811015610d7a578082015181840152602081019050610d5f565b50505050905001838103825284818151815260200191508051906020019080838360005b83811015610db9578082015181840152602081019050610d9e565b50505050905090810190601f168015610de65780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b610dfe613563565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610e4861358c565b604051808215151515815260200191505060405180910390f35b610f6f600480360360c0811015610e7857600080fd5b8101908080359060200190640100000000811115610e9557600080fd5b820183602082011115610ea757600080fd5b80359060200191846001830284011164010000000083111715610ec957600080fd5b909192939192939080359060200190640100000000811115610eea57600080fd5b820183602082011115610efc57600080fd5b80359060200191846001830284011164010000000083111715610f1e57600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506135ea565b005b610fb360048036036020811015610f8757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506136b1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6110586004803603608081101561100b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506137d8565b005b611062613b3f565b604051808215151515815260200191505060405180910390f35b611084613c78565b005b6110c86004803603602081101561109c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613da6565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156111085780820151818401526020810190506110ed565b50505050905090810190601f1680156111355780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6111856004803603602081101561115957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613e8a565b005b6111c96004803603602081101561119d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061402e565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156112095780820151818401526020810190506111ee565b50505050905090810190601f1680156112365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6112866004803603602081101561125a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614112565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61132b600480360360808110156112de57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614145565b005b61136f6004803603602081101561134357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506143ff565b604051808215151515815260200191505060405180910390f35b6114426004803603602081101561139f57600080fd5b81019080803590602001906401000000008111156113bc57600080fd5b8201836020820111156113ce57600080fd5b803590602001918460018302840111640100000000831117156113f057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506144b6565b005b6114866004803603602081101561145a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614644565b005b6114ca6004803603602081101561149e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506146f7565b005b60006114d782611f8e565b6114e057600080fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506115e98888888861477d565b878160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611637614a65565b73ffffffffffffffffffffffffffffffffffffffff16634e06fd8a338a87876040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b15801561171d57600080fd5b505af1158015611731573d6000803e3d6000fd5b505050506040513d602081101561174757600080fd5b81019080805190602001909291905050506117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806150936021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494389604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250600154811461189f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b50505050505050565b602181511015611920576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6461746120656e6372797074696f6e206b6579206c656e677468203c3d20333281525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508181600601908051906020019061197b929190614e25565b503373ffffffffffffffffffffffffffffffffffffffff167f43fdefe0a824cb0e3bbaf9c4bc97669187996136fe9282382baf10787f0d808d836040518080602001828103825283818151815260200191508051906020019080838360005b838110156119f55780820151818401526020810190506119da565b50505050905090810190601f168015611a225780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff167fa197481f404d8a8082368ad7445380f01e75f27dea6b7aef234a4ce071127fae8260010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260008160010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050611bc78c8c8c8c61477d565b8b8160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550611c15614a65565b73ffffffffffffffffffffffffffffffffffffffff1663713ea0f3338e8b8b8b8b8b8b6040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001806020018060200184810384528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508481038352888882818152602001925080828437600081840152601f19601f8201169050808301925050508481038252868682818152602001925080828437600081840152601f19601f8201169050808301925050509b505050505050505050505050602060405180830381600087803b158015611d6357600080fd5b505af1158015611d77573d6000803e3d6000fd5b505050506040513d6020811015611d8d57600080fd5b8101908080519060200190929190505050611e10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4661696c656420746f207570646174652076616c696461746f72206b6579730081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf949438d604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2506001548114611f02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050505050505050565b600260009054906101000a900460ff1681565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b6000611ff282611f8e565b612064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612108578061210a565b825b915050919050565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506121788686868661477d565b858160010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167faab5f8a189373aaa290f42ae65ea5d7971b732366ca5bf66556e76263944af2887604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25060015481146122b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600061235a82611f8e565b6123cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146124705780612472565b825b915050919050565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156125525780601f1061252757610100808354040283529160200191612552565b820191906000526020600020905b81548152906001019060200180831161253557829003601f168201915b50505050509050919050565b600061256982611f8e565b61257257600080fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600061262082611f8e565b612692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146127365780612738565b825b915050919050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146128cb578273ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146128c2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614fcb6026913960400191505060405180910390fd5b8091505061294b565b6128d483611f8e565b612946576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612adb578273ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612ad2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806150b46021913960400191505060405180910390fd5b80915050612b5b565b612ae483611f8e565b612b56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b612b6861358c565b612bda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b612ca233611f8e565b612d14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508282826007019190612d6a929190614ea5565b503373ffffffffffffffffffffffffffffffffffffffff167f0b5629fec5b6b5a1c2cfe0de7495111627a8cf297dced72e0669527425d3f01b848460405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff167f14670729407debb6ed03d885f8ba57155de89ce39bf17127ae4900ec7c2ad1038260010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260008160010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050612f678585858561477d565b848160010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f9dfbc5a621c3e2d0d83beee687a17dfc796bbce2118793e5e254409bb265ca0b86604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050505050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146131df578273ffffffffffffffffffffffffffffffffffffffff16600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806150176028913960400191505060405180910390fd5b8091505061325f565b6131e883611f8e565b61325a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f6e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b60608060008090506060858590506040519080825280602002602001820160405280156132a05781602001602082028038833980820191505090505b50905060008090505b8686905081101561338e57600360008888848181106132c457fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060070180546001816001161561010002031660029004905082828151811061333f57fe5b60200260200101818152505061337182828151811061335a57fe5b602002602001015184614b6090919063ffffffff16565b9250613387600182614b6090919063ffffffff16565b90506132a9565b506060826040519080825280601f01601f1916602001820160405280156133c45781602001600182028038833980820191505090505b509050600080905060008090505b888890508110156135515760008090505b8482815181106133ef57fe5b602002602001015181101561353557600360008b8b8581811061340e57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018181546001816001161561010002031660029004811061348457fe5b8154600116156134a35790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000028484815181106134d557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350613518600184614b6090919063ffffffff16565b925061352e600182614b6090919063ffffffff16565b90506133e3565b5061354a600182614b6090919063ffffffff16565b90506133d2565b50828295509550505050509250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166135ce614be8565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6135f333611f8e565b613601576135ff613b3f565b505b61364e88888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506144b6565b61369b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506118a8565b6136a7848484846137d8565b5050505050505050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461375357809150506137d3565b61375c83611f8e565b6137ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4e6f7420616e206163636f756e7400000000000000000000000000000000000081525060200191505060405180910390fd5b829150505b919050565b6137e133611f8e565b613853576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806138b95750600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b613a3857600073415406e7b0b8a511f4e9111c34793cb0b465f8e36396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561395857600080fd5b505af415801561396c573d6000803e3d6000fd5b505050506040513d602081101561398257600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614613a36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b505b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050848160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167ff81d74398fd47e35c36b714019df15f200f623dde569b5b531d6a0b4da5c5f2686604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050505050565b6000613b4a33614bf0565b8015613b5b5750613b5a33614c4a565b5b613bcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4163636f756e742065786973747300000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167f805996f252884581e2f74cf3d2b03564d5ec26ccc90850ae12653dc1b72d1fa260405160405180910390a2600191505090565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff167fa54764c62865ff0cd3f271fb1d4635662bff10f0878694f1654fb7fbdecb830d8260010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260008160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015613e7e5780601f10613e5357610100808354040283529160200191613e7e565b820191906000526020600020905b815481529060010190602001808311613e6157829003601f168201915b50505050509050919050565b613e9261358c565b613f04576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613fa7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156141065780601f106140db57610100808354040283529160200191614106565b820191906000526020600020905b8154815290600101906020018083116140e957829003601f168201915b50505050509050919050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60018060008282540192505081905550600060015490506000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506141ab8686868661477d565b858160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506141f9614a65565b73ffffffffffffffffffffffffffffffffffffffff1663facd743b336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561427557600080fd5b505afa158015614289573d6000803e3d6000fd5b505050506040513d602081101561429f57600080fd5b810190808051906020019092919050505015614306576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061503f6021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494387604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25060015481146143f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b600061440a82611f8e565b61441357600080fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b6144bf33611f8e565b614531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508181600501908051906020019061458c929190614f25565b503373ffffffffffffffffffffffffffffffffffffffff167fa6e2c5a23bb917ba0a584c4b250257ddad698685829b66a8813c004b39934fe4836040518080602001828103825283818151815260200191508051906020019080838360005b838110156146065780820151818401526020810190506145eb565b50505050905090810190601f1680156146335780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b600260009054906101000a900460ff16156146c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600260006101000a81548160ff0219169083151502179055506146eb33614ce1565b6146f481613e8a565b50565b6146ff61358c565b614771576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61477a81614ce1565b50565b61478633611f8e565b6147f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b61480184614bf0565b8015614812575061481184614c4a565b5b614867576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806150606033913960400191505060405180910390fd5b600073415406e7b0b8a511f4e9111c34793cb0b465f8e36396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561490257600080fd5b505af4158015614916573d6000803e3d6000fd5b505050506040513d602081101561492c57600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146149e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b33600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050565b6000600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f56616c696461746f727300000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614b2057600080fd5b505afa158015614b34573d6000803e3d6000fd5b505050506040513d6020811015614b4a57600080fd5b8101908080519060200190929190505050905090565b600080828401905083811015614bde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600033905090565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16159050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614d67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614ff16026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614e6657805160ff1916838001178555614e94565b82800160010185558215614e94579182015b82811115614e93578251825591602001919060010190614e78565b5b509050614ea19190614fa5565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614ee657803560ff1916838001178555614f14565b82800160010185558215614f14579182015b82811115614f13578235825591602001919060010190614ef8565b5b509050614f219190614fa5565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614f6657805160ff1916838001178555614f94565b82800160010185558215614f94579182015b82811115614f93578251825591602001919060010190614f78565b5b509050614fa19190614fa5565b5090565b614fc791905b80821115614fc3576000816000905550600101614fab565b5090565b9056fe6e6f742061637469766520617574686f72697a65642076616c696461746f72207369676e65724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573736e6f742061637469766520617574686f72697a6564206174746573746174696f6e207369676e657243616e6e6f7420617574686f72697a652076616c696461746f72207369676e657243616e6e6f742072652d617574686f72697a652061646472657373206f72206c6f636b656420676f6c64206163636f756e742e4661696c656420746f20757064617465204543445341207075626c6963206b65796e6f742061637469766520617574686f72697a656420766f7465207369676e6572a165627a7a72305820baa23b4cb7dd921c21f9fcbdaccd486b4e34561057b53adc4c1488eb0f021c660029

External libraries