Address Details
contract

0x0cc6E134ABd23d826d72C1Cb9331d1af66ac6a77

Contract Name
ReserveSpenderMultiSig
Creator
0xe23a4cā€“2b2dee at 0x7b75a2ā€“18bbaf
Balance
0 CELO ( )
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
10129143
Contract name:
ReserveSpenderMultiSig




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




Verified at
2020-04-22T22:03:50.486211Z

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

library Address {
    
    function isContract(address account) internal view returns (bool) {
        
        
        
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }

    
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        
        (bool success, ) = recipient.call.value(amount)("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }
}

contract Initializable {
  bool public initialized;

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

contract MultiSig is Initializable {
  using SafeMath for uint256;
  
  event Confirmation(address indexed sender, uint256 indexed transactionId);
  event Revocation(address indexed sender, uint256 indexed transactionId);
  event Submission(uint256 indexed transactionId);
  event Execution(uint256 indexed transactionId, bytes returnData);
  event Deposit(address indexed sender, uint256 value);
  event OwnerAddition(address indexed owner);
  event OwnerRemoval(address indexed owner);
  event RequirementChange(uint256 required);
  event InternalRequirementChange(uint256 internalRequired);

  
  uint256 public constant MAX_OWNER_COUNT = 50;

  
  mapping(uint256 => Transaction) public transactions;
  mapping(uint256 => mapping(address => bool)) public confirmations;
  mapping(address => bool) public isOwner;
  address[] public owners;
  uint256 public required;
  uint256 public internalRequired;
  uint256 public transactionCount;

  struct Transaction {
    address destination;
    uint256 value;
    bytes data;
    bool executed;
  }

  
  modifier onlyWallet() {
    require(msg.sender == address(this), "msg.sender was not multisig wallet");
    _;
  }

  modifier ownerDoesNotExist(address owner) {
    require(!isOwner[owner], "owner already existed");
    _;
  }

  modifier ownerExists(address owner) {
    require(isOwner[owner], "owner does not exist");
    _;
  }

  modifier transactionExists(uint256 transactionId) {
    require(transactions[transactionId].destination != address(0), "transaction does not exist");
    _;
  }

  modifier confirmed(uint256 transactionId, address owner) {
    require(confirmations[transactionId][owner], "transaction was not confirmed for owner");
    _;
  }

  modifier notConfirmed(uint256 transactionId, address owner) {
    require(!confirmations[transactionId][owner], "transaction was already confirmed for owner");
    _;
  }

  modifier notExecuted(uint256 transactionId) {
    require(!transactions[transactionId].executed, "transaction was executed already");
    _;
  }

  modifier notNull(address _address) {
    require(_address != address(0), "address was null");
    _;
  }

  modifier validRequirement(uint256 ownerCount, uint256 _required) {
    require(
      ownerCount <= MAX_OWNER_COUNT && _required <= ownerCount && _required != 0 && ownerCount != 0,
      "invalid requirement"
    );
    _;
  }

  
  function() external payable {
    if (msg.value > 0) emit Deposit(msg.sender, msg.value);
  }

  
  
  
  
  
  function initialize(address[] calldata _owners, uint256 _required, uint256 _internalRequired)
    external
    initializer
    validRequirement(_owners.length, _required)
    validRequirement(_owners.length, _internalRequired)
  {
    for (uint256 i = 0; i < _owners.length; i = i.add(1)) {
      require(
        !isOwner[_owners[i]] && _owners[i] != address(0),
        "owner was null or already given owner status"
      );
      isOwner[_owners[i]] = true;
    }
    owners = _owners;
    required = _required;
    internalRequired = _internalRequired;
  }

  
  
  function addOwner(address owner)
    external
    onlyWallet
    ownerDoesNotExist(owner)
    notNull(owner)
    validRequirement(owners.length.add(1), internalRequired)
  {
    isOwner[owner] = true;
    owners.push(owner);
    emit OwnerAddition(owner);
  }

  
  
  function removeOwner(address owner) external onlyWallet ownerExists(owner) {
    isOwner[owner] = false;
    for (uint256 i = 0; i < owners.length.sub(1); i = i.add(1))
      if (owners[i] == owner) {
        owners[i] = owners[owners.length.sub(1)];
        break;
      }
    owners.length = owners.length.sub(1);
    if (required > owners.length) changeRequirement(owners.length);
    if (internalRequired > owners.length) changeInternalRequirement(owners.length);
    emit OwnerRemoval(owner);
  }

  
  
  
  function replaceOwner(address owner, address newOwner)
    external
    onlyWallet
    ownerExists(owner)
    notNull(newOwner)
    ownerDoesNotExist(newOwner)
  {
    for (uint256 i = 0; i < owners.length; i = i.add(1))
      if (owners[i] == owner) {
        owners[i] = newOwner;
        break;
      }
    isOwner[owner] = false;
    isOwner[newOwner] = true;
    emit OwnerRemoval(owner);
    emit OwnerAddition(newOwner);
  }

  
  
  
  function changeRequirement(uint256 _required)
    public
    onlyWallet
    validRequirement(owners.length, _required)
  {
    required = _required;
    emit RequirementChange(_required);
  }

  
  
  
  function changeInternalRequirement(uint256 _internalRequired)
    public
    onlyWallet
    validRequirement(owners.length, _internalRequired)
  {
    internalRequired = _internalRequired;
    emit InternalRequirementChange(_internalRequired);
  }

  
  
  
  
  
  function submitTransaction(address destination, uint256 value, bytes calldata data)
    external
    returns (uint256 transactionId)
  {
    transactionId = addTransaction(destination, value, data);
    confirmTransaction(transactionId);
  }

  
  
  function confirmTransaction(uint256 transactionId)
    public
    ownerExists(msg.sender)
    transactionExists(transactionId)
    notConfirmed(transactionId, msg.sender)
  {
    confirmations[transactionId][msg.sender] = true;
    emit Confirmation(msg.sender, transactionId);
    if (isConfirmed(transactionId)) {
      executeTransaction(transactionId);
    }
  }

  
  
  function revokeConfirmation(uint256 transactionId)
    external
    ownerExists(msg.sender)
    confirmed(transactionId, msg.sender)
    notExecuted(transactionId)
  {
    confirmations[transactionId][msg.sender] = false;
    emit Revocation(msg.sender, transactionId);
  }

  
  
  function executeTransaction(uint256 transactionId)
    public
    ownerExists(msg.sender)
    confirmed(transactionId, msg.sender)
    notExecuted(transactionId)
  {
    require(isConfirmed(transactionId), "Transaction not confirmed.");
    Transaction storage txn = transactions[transactionId];
    txn.executed = true;
    bool success;
    bytes memory returnData;
    (success, returnData) = external_call(txn.destination, txn.value, txn.data);
    require(success, "Transaction execution failed.");
    emit Execution(transactionId, returnData);
  }

  
  
  function external_call(address destination, uint256 value, bytes memory data)
    private
    returns (bool, bytes memory)
  {
    if (data.length > 0) require(Address.isContract(destination), "Invalid contract address");
    bool success;
    bytes memory returnData;
    (success, returnData) = destination.call.value(value)(data);
    return (success, returnData);
  }

  
  
  
  function isConfirmed(uint256 transactionId) public view returns (bool) {
    uint256 count = 0;
    for (uint256 i = 0; i < owners.length; i = i.add(1)) {
      if (confirmations[transactionId][owners[i]]) count = count.add(1);
      bool isInternal = transactions[transactionId].destination == address(this);
      if ((isInternal && count == internalRequired) || (!isInternal && count == required))
        return true;
    }
    return false;
  }

  
  
  
  
  
  
  function addTransaction(address destination, uint256 value, bytes memory data)
    internal
    notNull(destination)
    returns (uint256 transactionId)
  {
    transactionId = transactionCount;
    transactions[transactionId] = Transaction({
      destination: destination,
      value: value,
      data: data,
      executed: false
    });
    transactionCount = transactionCount.add(1);
    emit Submission(transactionId);
  }

  
  
  
  
  function getConfirmationCount(uint256 transactionId) external view returns (uint256 count) {
    for (uint256 i = 0; i < owners.length; i = i.add(1))
      if (confirmations[transactionId][owners[i]]) count = count.add(1);
  }

  
  
  
  
  function getTransactionCount(bool pending, bool executed) external view returns (uint256 count) {
    for (uint256 i = 0; i < transactionCount; i = i.add(1))
      if ((pending && !transactions[i].executed) || (executed && transactions[i].executed))
        count = count.add(1);
  }

  
  
  function getOwners() external view returns (address[] memory) {
    return owners;
  }

  
  
  
  function getConfirmations(uint256 transactionId)
    external
    view
    returns (address[] memory _confirmations)
  {
    address[] memory confirmationsTemp = new address[](owners.length);
    uint256 count = 0;
    uint256 i;
    for (i = 0; i < owners.length; i = i.add(1))
      if (confirmations[transactionId][owners[i]]) {
        confirmationsTemp[count] = owners[i];
        count = count.add(1);
      }
    _confirmations = new address[](count);
    for (i = 0; i < count; i = i.add(1)) _confirmations[i] = confirmationsTemp[i];
  }

  
  
  
  
  
  
  function getTransactionIds(uint256 from, uint256 to, bool pending, bool executed)
    external
    view
    returns (uint256[] memory _transactionIds)
  {
    uint256[] memory transactionIdsTemp = new uint256[](transactionCount);
    uint256 count = 0;
    uint256 i;
    for (i = 0; i < transactionCount; i = i.add(1))
      if ((pending && !transactions[i].executed) || (executed && transactions[i].executed)) {
        transactionIdsTemp[count] = i;
        count = count.add(1);
      }
    _transactionIds = new uint256[](to.sub(from));
    for (i = from; i < to; i = i.add(1)) _transactionIds[i.sub(from)] = transactionIdsTemp[i];
  }
}

contract ReserveSpenderMultiSig is MultiSig {}
        

Contract ABI

[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owners","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"initialized","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"owner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"revokeConfirmation","inputs":[{"type":"uint256","name":"transactionId"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"changeInternalRequirement","inputs":[{"type":"uint256","name":"_internalRequired"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isOwner","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"confirmations","inputs":[{"type":"uint256","name":""},{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"count"}],"name":"getTransactionCount","inputs":[{"type":"bool","name":"pending"},{"type":"bool","name":"executed"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address[]","name":"_owners"},{"type":"uint256","name":"_required"},{"type":"uint256","name":"_internalRequired"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addOwner","inputs":[{"type":"address","name":"owner"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isConfirmed","inputs":[{"type":"uint256","name":"transactionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"count"}],"name":"getConfirmationCount","inputs":[{"type":"uint256","name":"transactionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"destination"},{"type":"uint256","name":"value"},{"type":"bytes","name":"data"},{"type":"bool","name":"executed"}],"name":"transactions","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":""}],"name":"getOwners","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"internalRequired","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":"_transactionIds"}],"name":"getTransactionIds","inputs":[{"type":"uint256","name":"from"},{"type":"uint256","name":"to"},{"type":"bool","name":"pending"},{"type":"bool","name":"executed"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"_confirmations"}],"name":"getConfirmations","inputs":[{"type":"uint256","name":"transactionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"transactionCount","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"changeRequirement","inputs":[{"type":"uint256","name":"_required"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"confirmTransaction","inputs":[{"type":"uint256","name":"transactionId"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"transactionId"}],"name":"submitTransaction","inputs":[{"type":"address","name":"destination"},{"type":"uint256","name":"value"},{"type":"bytes","name":"data"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"MAX_OWNER_COUNT","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"required","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"replaceOwner","inputs":[{"type":"address","name":"owner"},{"type":"address","name":"newOwner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"executeTransaction","inputs":[{"type":"uint256","name":"transactionId"}],"constant":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"event","name":"Confirmation","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Revocation","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Submission","inputs":[{"type":"uint256","name":"transactionId","indexed":true}],"anonymous":false},{"type":"event","name":"Execution","inputs":[{"type":"uint256","name":"transactionId","indexed":true},{"type":"bytes","name":"returnData","indexed":false}],"anonymous":false},{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"sender","indexed":true},{"type":"uint256","name":"value","indexed":false}],"anonymous":false},{"type":"event","name":"OwnerAddition","inputs":[{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"OwnerRemoval","inputs":[{"type":"address","name":"owner","indexed":true}],"anonymous":false},{"type":"event","name":"RequirementChange","inputs":[{"type":"uint256","name":"required","indexed":false}],"anonymous":false},{"type":"event","name":"InternalRequirementChange","inputs":[{"type":"uint256","name":"internalRequired","indexed":false}],"anonymous":false}]
            

Deployed ByteCode

0x6080604052600436106101665760003560e01c80639ace38c2116100d1578063ba51a6df1161008a578063d74f8edd11610064578063d74f8edd14610a2e578063dc8452cd14610a59578063e20056e614610a84578063ee22610b14610af557610166565b8063ba51a6df146108f4578063c01a8c841461092f578063c64274741461096a57610166565b80639ace38c2146105f7578063a0e67e2b146106f0578063a24efcdf1461075c578063a8abe69a14610787578063b5dc40c314610839578063b77bf600146108c957610166565b80633411c81c116101235780633411c81c1461039a578063547415251461040d5780635eae79591461046a5780637065cb4814610504578063784547a7146105555780638b51d13f146105a857610166565b8063025e7c27146101c0578063158ef93e1461023b578063173825d91461026a57806320ea8d86146102bb5780632e6c3721146102f65780632f54bf6e14610331575b60003411156101be573373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a25b005b3480156101cc57600080fd5b506101f9600480360360208110156101e357600080fd5b8101908080359060200190929190505050610b30565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561024757600080fd5b50610250610b6c565b604051808215151515815260200191505060405180910390f35b34801561027657600080fd5b506102b96004803603602081101561028d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b7e565b005b3480156102c757600080fd5b506102f4600480360360208110156102de57600080fd5b8101908080359060200190929190505050610f1b565b005b34801561030257600080fd5b5061032f6004803603602081101561031957600080fd5b81019080803590602001909291905050506111dc565b005b34801561033d57600080fd5b506103806004803603602081101561035457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611347565b604051808215151515815260200191505060405180910390f35b3480156103a657600080fd5b506103f3600480360360408110156103bd57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611367565b604051808215151515815260200191505060405180910390f35b34801561041957600080fd5b506104546004803603604081101561043057600080fd5b81019080803515159060200190929190803515159060200190929190505050611396565b6040518082815260200191505060405180910390f35b34801561047657600080fd5b506105026004803603606081101561048d57600080fd5b81019080803590602001906401000000008111156104aa57600080fd5b8201836020820111156104bc57600080fd5b803590602001918460208302840111640100000000831117156104de57600080fd5b90919293919293908035906020019092919080359060200190929190505050611448565b005b34801561051057600080fd5b506105536004803603602081101561052757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061182b565b005b34801561056157600080fd5b5061058e6004803603602081101561057857600080fd5b8101908080359060200190929190505050611bd5565b604051808215151515815260200191505060405180910390f35b3480156105b457600080fd5b506105e1600480360360208110156105cb57600080fd5b8101908080359060200190929190505050611d66565b6040518082815260200191505060405180910390f35b34801561060357600080fd5b506106306004803603602081101561061a57600080fd5b8101908080359060200190929190505050611e4d565b604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b838110156106b2578082015181840152602081019050610697565b50505050905090810190601f1680156106df5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b3480156106fc57600080fd5b50610705611f42565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561074857808201518184015260208101905061072d565b505050509050019250505060405180910390f35b34801561076857600080fd5b50610771611fd0565b6040518082815260200191505060405180910390f35b34801561079357600080fd5b506107e2600480360360808110156107aa57600080fd5b810190808035906020019092919080359060200190929190803515159060200190929190803515159060200190929190505050611fd6565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561082557808201518184015260208101905061080a565b505050509050019250505060405180910390f35b34801561084557600080fd5b506108726004803603602081101561085c57600080fd5b8101908080359060200190929190505050612188565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156108b557808201518184015260208101905061089a565b505050509050019250505060405180910390f35b3480156108d557600080fd5b506108de6123e0565b6040518082815260200191505060405180910390f35b34801561090057600080fd5b5061092d6004803603602081101561091757600080fd5b81019080803590602001909291905050506123e6565b005b34801561093b57600080fd5b506109686004803603602081101561095257600080fd5b8101908080359060200190929190505050612551565b005b34801561097657600080fd5b50610a186004803603606081101561098d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001906401000000008111156109d457600080fd5b8201836020820111156109e657600080fd5b80359060200191846001830284011164010000000083111715610a0857600080fd5b909192939192939050505061286d565b6040518082815260200191505060405180910390f35b348015610a3a57600080fd5b50610a436128d1565b6040518082815260200191505060405180910390f35b348015610a6557600080fd5b50610a6e6128d6565b6040518082815260200191505060405180910390f35b348015610a9057600080fd5b50610af360048036036040811015610aa757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506128dc565b005b348015610b0157600080fd5b50610b2e60048036036020811015610b1857600080fd5b8101908080359060200190929190505050612db7565b005b60048181548110610b3d57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900460ff1681565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139806022913960400191505060405180910390fd5b80600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610cc2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060008090505b610d39600160048054905061326890919063ffffffff16565b811015610e70578273ffffffffffffffffffffffffffffffffffffffff1660048281548110610d6457fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610e55576004610dc6600160048054905061326890919063ffffffff16565b81548110610dd057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660048281548110610e0857fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610e70565b610e696001826132b290919063ffffffff16565b9050610d20565b50610e8a600160048054905061326890919063ffffffff16565b600481610e979190613779565b506004805490506005541115610eb657610eb56004805490506123e6565b5b6004805490506006541115610ed457610ed36004805490506111dc565b5b8173ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a25050565b33600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610fdb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81336002600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611090576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806139596027913960400191505060405180910390fd5b836001600082815260200190815260200160002060030160009054906101000a900460ff1615611128576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f7472616e73616374696f6e2077617320657865637574656420616c726561647981525060200191505060405180910390fd5b60006002600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167ff6a317157440607f36269043eb55f1287a5a19ba2216afeab88cd46cbcfb88e960405160405180910390a35050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611260576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139806022913960400191505060405180910390fd5b60048054905081603282111580156112785750818111155b8015611285575060008114155b8015611292575060008214155b611304576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b826006819055507fa07eff79ea50418b0e96ff7c01d65eb6c3a5a240ee91cd81c70c89503dd41239836040518082815260200191505060405180910390a1505050565b60036020528060005260406000206000915054906101000a900460ff1681565b60026020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b600080600090505b600754811015611441578380156113d657506001600082815260200190815260200160002060030160009054906101000a900460ff16155b8061140a575082801561140957506001600082815260200190815260200160002060030160009054906101000a900460ff165b5b15611426576114236001836132b290919063ffffffff16565b91505b61143a6001826132b290919063ffffffff16565b905061139e565b5092915050565b6000809054906101000a900460ff16156114ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b60016000806101000a81548160ff0219169083151502179055508383905082603282111580156114fa5750818111155b8015611507575060008114155b8015611514575060008214155b611586576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b85859050836032821115801561159c5750818111155b80156115a9575060008114155b80156115b6575060008214155b611628576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b60008090505b8888905081101561180057600360008a8a8481811061164957fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161580156117105750600073ffffffffffffffffffffffffffffffffffffffff168989838181106116da57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b611765576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001806139a2602c913960400191505060405180910390fd5b6001600360008b8b8581811061177757fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506117f96001826132b290919063ffffffff16565b905061162e565b508787600491906118129291906137a5565b5085600581905550846006819055505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139806022913960400191505060405180910390fd5b80600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611970576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f6f776e657220616c72656164792065786973746564000000000000000000000081525060200191505060405180910390fd5b81600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a14576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f6164647265737320776173206e756c6c0000000000000000000000000000000081525060200191505060405180910390fd5b611a2d60016004805490506132b290919063ffffffff16565b60065460328211158015611a415750818111155b8015611a4e575060008114155b8015611a5b575060008214155b611acd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b6001600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060048590806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508473ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b6000806000905060008090505b600480549050811015611d5a5760026000858152602001908152602001600020600060048381548110611c1157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611ca057611c9d6001836132b290919063ffffffff16565b91505b60003073ffffffffffffffffffffffffffffffffffffffff166001600087815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050808015611d17575060065483145b80611d2d575080158015611d2c575060055483145b5b15611d3e5760019350505050611d61565b50611d536001826132b290919063ffffffff16565b9050611be2565b5060009150505b919050565b600080600090505b600480549050811015611e475760026000848152602001908152602001600020600060048381548110611d9d57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611e2c57611e296001836132b290919063ffffffff16565b91505b611e406001826132b290919063ffffffff16565b9050611d6e565b50919050565b60016020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690806001015490806002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611f255780601f10611efa57610100808354040283529160200191611f25565b820191906000526020600020905b815481529060010190602001808311611f0857829003601f168201915b5050505050908060030160009054906101000a900460ff16905084565b60606004805480602002602001604051908101604052809291908181526020018280548015611fc657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311611f7c575b5050505050905090565b60065481565b60608060075460405190808252806020026020018201604052801561200a5781602001602082028038833980820191505090505b509050600080905060008090505b6007548110156120d45785801561205057506001600082815260200190815260200160002060030160009054906101000a900460ff16155b80612084575084801561208357506001600082815260200190815260200160002060030160009054906101000a900460ff165b5b156120b9578083838151811061209657fe5b6020026020010181815250506120b66001836132b290919063ffffffff16565b91505b6120cd6001826132b290919063ffffffff16565b9050612018565b6120e7888861326890919063ffffffff16565b6040519080825280602002602001820160405280156121155781602001602082028038833980820191505090505b5093508790505b8681101561217d5782818151811061213057fe5b60200260200101518461214c8a8461326890919063ffffffff16565b8151811061215657fe5b6020026020010181815250506121766001826132b290919063ffffffff16565b905061211c565b505050949350505050565b6060806004805490506040519080825280602002602001820160405280156121bf5781602001602082028038833980820191505090505b509050600080905060008090505b60048054905081101561232457600260008681526020019081526020016000206000600483815481106121fc57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612309576004818154811061228157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383815181106122b857fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506123066001836132b290919063ffffffff16565b91505b61231d6001826132b290919063ffffffff16565b90506121cd565b816040519080825280602002602001820160405280156123535781602001602082028038833980820191505090505b509350600090505b818110156123d85782818151811061236f57fe5b602002602001015184828151811061238357fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506123d16001826132b290919063ffffffff16565b905061235b565b505050919050565b60075481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461246a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139806022913960400191505060405180910390fd5b60048054905081603282111580156124825750818111155b801561248f575060008114155b801561249c575060008214155b61250e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f696e76616c696420726571756972656d656e740000000000000000000000000081525060200191505060405180910390fd5b826005819055507fa3f1ee9126a074d9326c682f561767f710e927faa811f7a99829d49dc421797a836040518082815260200191505060405180910390a1505050565b33600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612611576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81600073ffffffffffffffffffffffffffffffffffffffff166001600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156126eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f7472616e73616374696f6e20646f6573206e6f7420657869737400000000000081525060200191505060405180910390fd5b82336002600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156127a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061392e602b913960400191505060405180910390fd5b60016002600087815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550843373ffffffffffffffffffffffffffffffffffffffff167f4a504a94899432a9846e1aa406dceb1bcfd538bb839071d49d1e5e23f5be30ef60405160405180910390a361285785611bd5565b156128665761286585612db7565b5b5050505050565b60006128be858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061333a565b90506128c981612551565b949350505050565b603281565b60055481565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806139806022913960400191505060405180910390fd5b81600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612a20576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612ac4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f6164647265737320776173206e756c6c0000000000000000000000000000000081525060200191505060405180910390fd5b82600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612b85576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f6f776e657220616c72656164792065786973746564000000000000000000000081525060200191505060405180910390fd5b60008090505b600480549050811015612c79578573ffffffffffffffffffffffffffffffffffffffff1660048281548110612bbc57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612c5e578460048281548110612c1157fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550612c79565b612c726001826132b290919063ffffffff16565b9050612b8b565b506000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508473ffffffffffffffffffffffffffffffffffffffff167f8001553a916ef2f495d26a907cc54d96ed840d7bda71e73194bf5a9df7a76b9060405160405180910390a28373ffffffffffffffffffffffffffffffffffffffff167ff39e6e1eb0edcf53c221607b54b00cd28f3196fed0a24994dc308b8f611b682d60405160405180910390a25050505050565b33600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612e77576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f6f776e657220646f6573206e6f7420657869737400000000000000000000000081525060200191505060405180910390fd5b81336002600083815260200190815260200160002060008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16612f2c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806139596027913960400191505060405180910390fd5b836001600082815260200190815260200160002060030160009054906101000a900460ff1615612fc4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f7472616e73616374696f6e2077617320657865637574656420616c726561647981525060200191505060405180910390fd5b612fcd85611bd5565b61303f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f5472616e73616374696f6e206e6f7420636f6e6669726d65642e00000000000081525060200191505060405180910390fd5b600060016000878152602001908152602001600020905060018160030160006101000a81548160ff021916908315150217905550600060606131468360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168460010154856002018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561313c5780601f106131115761010080835404028352916020019161313c565b820191906000526020600020905b81548152906001019060200180831161311f57829003601f168201915b5050505050613514565b8092508193505050816131c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5472616e73616374696f6e20657865637574696f6e206661696c65642e00000081525060200191505060405180910390fd5b877f0c18aae526accb31b01cf9a15bdf435e70632ee31efc4c5c0752c4262ea45d2f826040518080602001828103825283818151815260200191508051906020019080838360005b83811015613224578082015181840152602081019050613209565b50505050905090810190601f1680156132515780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050505050505050565b60006132aa83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061366e565b905092915050565b600080828401905083811015613330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600083600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156133e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f6164647265737320776173206e756c6c0000000000000000000000000000000081525060200191505060405180910390fd5b600754915060405180608001604052808673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001600015158152506001600084815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010155604082015181600201908051906020019061349f929190613845565b5060608201518160030160006101000a81548160ff0219169083151502179055509050506134d960016007546132b290919063ffffffff16565b600781905550817fc0ba8fe4b176c1714197d43b9cc6bcf797a4a7461c5fe8d0ef6e184ae7601e5160405160405180910390a2509392505050565b6000606060008351111561359e5761352b8561372e565b61359d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b5b600060608673ffffffffffffffffffffffffffffffffffffffff1686866040518082805190602001908083835b602083106135ee57805182526020820191506020810190506020830392506135cb565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613650576040519150601f19603f3d011682016040523d82523d6000602084013e613655565b606091505b5080925081935050508181935093505050935093915050565b600083831115829061371b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156136e05780820151818401526020810190506136c5565b50505050905090810190601f16801561370d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561377057506000801b8214155b92505050919050565b8154818355818111156137a05781836000526020600020918201910161379f91906138c5565b5b505050565b828054828255906000526020600020908101928215613834579160200282015b8281111561383357823573ffffffffffffffffffffffffffffffffffffffff168260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906137c5565b5b50905061384191906138ea565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061388657805160ff19168380011785556138b4565b828001600101855582156138b4579182015b828111156138b3578251825591602001919060010190613898565b5b5090506138c191906138c5565b5090565b6138e791905b808211156138e35760008160009055506001016138cb565b5090565b90565b61392a91905b8082111561392657600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016138f0565b5090565b9056fe7472616e73616374696f6e2077617320616c726561647920636f6e6669726d656420666f72206f776e65727472616e73616374696f6e20776173206e6f7420636f6e6669726d656420666f72206f776e65726d73672e73656e64657220776173206e6f74206d756c74697369672077616c6c65746f776e657220776173206e756c6c206f7220616c726561647920676976656e206f776e657220737461747573a165627a7a723058209c8c6d96bb432a17ff751f4cdee904bf41217ab5e87c3fc17a3f9856e4ca2ea60029