Address Details
contract

0x9F9037cE8deB6e8EF3045aD5C1a31D93895446C4

Contract Name
CeloProxyPriceProvider
Creator
0xac4b96–fcb761 at 0xed629b–11d98d
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
2 Transactions
Transfers
0 Transfers
Gas Used
14,570
Last Balance Update
25323413
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
CeloProxyPriceProvider




Optimization enabled
false
Compiler version
v0.6.12+commit.27d51765




EVM Version
istanbul




Verified at
2022-04-12T22:24:03.093246Z

contracts/CeloProxyPriceProviderFlattened.sol

pragma solidity 0.6.12;

library SafeMath {
  /**
   * @dev Returns the addition of two unsigned integers, reverting on
   * overflow.
   *
   * Counterpart to Solidity's `+` operator.
   *
   * Requirements:
   * - Addition cannot overflow.
   */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, 'SafeMath: addition overflow');

    return c;
  }

  /**
   * @dev Returns the subtraction of two unsigned integers, reverting on
   * overflow (when the result is negative).
   *
   * Counterpart to Solidity's `-` operator.
   *
   * Requirements:
   * - Subtraction cannot overflow.
   */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    return sub(a, b, 'SafeMath: subtraction overflow');
  }

  /**
   * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
   * overflow (when the result is negative).
   *
   * Counterpart to Solidity's `-` operator.
   *
   * Requirements:
   * - Subtraction cannot overflow.
   */
  function sub(
    uint256 a,
    uint256 b,
    string memory errorMessage
  ) internal pure returns (uint256) {
    require(b <= a, errorMessage);
    uint256 c = a - b;

    return c;
  }

  /**
   * @dev Returns the multiplication of two unsigned integers, reverting on
   * overflow.
   *
   * Counterpart to Solidity's `*` operator.
   *
   * Requirements:
   * - Multiplication cannot overflow.
   */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
    if (a == 0) {
      return 0;
    }

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

    return c;
  }

  /**
   * @dev Returns the integer division of two unsigned integers. Reverts on
   * division by zero. The result is rounded towards zero.
   *
   * Counterpart to Solidity's `/` operator. Note: this function uses a
   * `revert` opcode (which leaves remaining gas untouched) while Solidity
   * uses an invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   * - The divisor cannot be zero.
   */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    return div(a, b, 'SafeMath: division by zero');
  }

  /**
   * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
   * division by zero. The result is rounded towards zero.
   *
   * Counterpart to Solidity's `/` operator. Note: this function uses a
   * `revert` opcode (which leaves remaining gas untouched) while Solidity
   * uses an invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   * - The divisor cannot be zero.
   */
  function div(
    uint256 a,
    uint256 b,
    string memory errorMessage
  ) internal pure returns (uint256) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
   * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
   * Reverts when dividing by zero.
   *
   * Counterpart to Solidity's `%` operator. This function uses a `revert`
   * opcode (which leaves remaining gas untouched) while Solidity uses an
   * invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   * - The divisor cannot be zero.
   */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    return mod(a, b, 'SafeMath: modulo by zero');
  }

  /**
   * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
   * Reverts with custom message when dividing by zero.
   *
   * Counterpart to Solidity's `%` operator. This function uses a `revert`
   * opcode (which leaves remaining gas untouched) while Solidity uses an
   * invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   * - The divisor cannot be zero.
   */
  function mod(
    uint256 a,
    uint256 b,
    string memory errorMessage
  ) internal pure returns (uint256) {
    require(b != 0, errorMessage);
    return a % b;
  }
}

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

  function _msgData() internal view virtual returns (bytes memory) {
    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    return msg.data;
  }
}
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable is Context {
  address private _owner;

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

  /**
   * @dev Initializes the contract setting the deployer as the initial owner.
   */
  constructor() internal {
    address msgSender = _msgSender();
    _owner = msgSender;
    emit OwnershipTransferred(address(0), msgSender);
  }

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

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

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

  /**
   * @dev Transfers ownership of the contract to a new account (`newOwner`).
   * Can only be called by the current owner.
   */
  function transferOwnership(address newOwner) public virtual onlyOwner {
    require(newOwner != address(0), 'Ownable: new owner is the zero address');
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
  }
}

interface IPriceOracleGetter {
  /**
   * @dev returns the asset price in ETH
   * @param asset the address of the asset
   * @return the ETH price of the asset
   **/
  function getAssetPrice(address asset) external view returns (uint256);
}

interface IPriceFeed {

    // note this will always return 0 before update has been called successfully for the first time.
    function consult() external view returns (uint);

}

interface IRegistry {
  function getAddressForOrDie(bytes32) external view returns (address);
}

/// @title CeloProxyPriceProvider
/// @author Moola
/// @notice Proxy smart contract to get the price of an asset from a price source, with Celo SortedOracles
///         smart contracts as primary option
/// - If the returned price by a SortedOracles is <= 0, the call is forwarded to a fallbackOracle
/// - Owned by the Moola governance system, allowed to add sources for assets, replace them
///   and change the fallbackOracle

contract CeloProxyPriceProvider is IPriceOracleGetter, Ownable {
  using SafeMath for uint256;

  mapping(address => address) internal priceFeeds;
  IRegistry public immutable registry;

  constructor(
    address[] memory _assets,
    address[] memory _priceFeeds,
    address _registry
  ) public {
    updateAssets(_assets, _priceFeeds);
    registry = IRegistry(_registry);
  }

  function updateAssets(address[] memory _assets, address[] memory _priceFeeds) public onlyOwner {
    require(_assets.length == _priceFeeds.length, 'the quantity does not match');

    for (uint256 i = 0; i < _assets.length; i++) {
      priceFeeds[_assets[i]] = _priceFeeds[i];
    }
  }

  /// @notice Gets an asset price by address
  /// @param _asset The asset address
  function getAssetPrice(address _asset) public view override returns (uint256) {
    if (_asset == registry.getAddressForOrDie(keccak256(abi.encodePacked('GoldToken')))) {
      return 1 ether;
    }

    return (IPriceFeed(priceFeeds[_asset]).consult());
  }

  /// @notice Gets a list of prices from a list of assets addresses
  /// @param _assets The list of assets addresses
  function getAssetsPrices(address[] memory _assets) public view returns (uint256[] memory) {
    uint256[] memory prices = new uint256[](_assets.length);
    for (uint256 i = 0; i < _assets.length; i++) {
      prices[i] = getAssetPrice(_assets[i]);
    }

    return prices;
  }

  /// @notice Gets the address of the fallback oracle
  /// @return address The addres of the fallback oracle
  function getPriceFeed(address _asset) public view returns (address) {
    return (priceFeeds[_asset]);
  }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address[]","name":"_assets","internalType":"address[]"},{"type":"address[]","name":"_priceFeeds","internalType":"address[]"},{"type":"address","name":"_registry","internalType":"address"}]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getAssetPrice","inputs":[{"type":"address","name":"_asset","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getAssetsPrices","inputs":[{"type":"address[]","name":"_assets","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getPriceFeed","inputs":[{"type":"address","name":"_asset","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IRegistry"}],"name":"registry","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateAssets","inputs":[{"type":"address[]","name":"_assets","internalType":"address[]"},{"type":"address[]","name":"_priceFeeds","internalType":"address[]"}]}]
              

Contract Creation Code

0x60a06040523480156200001157600080fd5b506040516200128538038062001285833981810160405260608110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b838201915060208201858111156200006f57600080fd5b82518660208202830111640100000000821117156200008d57600080fd5b8083526020830192505050908051906020019060200280838360005b83811015620000c6578082015181840152602081019050620000a9565b5050505090500160405260200180516040519392919084640100000000821115620000f057600080fd5b838201915060208201858111156200010757600080fd5b82518660208202830111640100000000821117156200012557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156200015e57808201518184015260208101905062000141565b505050509050016040526020018051906020019092919050505060006200018a6200027a60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506200023a83836200028260201b60201c565b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b8152505050505062000491565b600033905090565b620002926200027a60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161462000353576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b8051825114620003cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f746865207175616e7469747920646f6573206e6f74206d61746368000000000081525060200191505060405180910390fd5b60005b82518110156200048c57818181518110620003e557fe5b602002602001015160016000858481518110620003fe57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508080600101915050620003ce565b505050565b60805160601c610dd1620004b46000398061085452806109475250610dd16000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146102855780639d23d9f2146102b9578063b3596f07146103c6578063f2fde38b1461041e57610088565b80634f568d1f1461008d5780635b6cca80146101d9578063715018a6146102475780637b10399914610251575b600080fd5b6101d7600480360360408110156100a357600080fd5b81019080803590602001906401000000008111156100c057600080fd5b8201836020820111156100d257600080fd5b803590602001918460208302840111640100000000831117156100f457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561015457600080fd5b82018360208201111561016657600080fd5b8035906020019184602083028401116401000000008311171561018857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050610462565b005b61021b600480360360208110156101ef57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610663565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61024f6106cc565b005b610259610852565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61028d610876565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61036f600480360360208110156102cf57600080fd5b81019080803590602001906401000000008111156102ec57600080fd5b8201836020820111156102fe57600080fd5b8035906020019184602083028401116401000000008311171561032057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061089f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103b2578082015181840152602081019050610397565b505050509050019250505060405180910390f35b610408600480360360208110156103dc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610943565b6040518082815260200191505060405180910390f35b6104606004803603602081101561043457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b62565b005b61046a610d6d565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461052a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80518251146105a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f746865207175616e7469747920646f6573206e6f74206d61746368000000000081525060200191505060405180910390fd5b60005b825181101561065e578181815181106105b957fe5b6020026020010151600160008584815181106105d157fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506105a4565b505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6106d4610d6d565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610794576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606080825167ffffffffffffffff811180156108ba57600080fd5b506040519080825280602002602001820160405280156108e95781602001602082028036833780820191505090505b50905060005b83518110156109395761091484828151811061090757fe5b6020026020010151610943565b82828151811061092057fe5b60200260200101818152505080806001019150506108ef565b5080915050919050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156109fc57600080fd5b505afa158015610a10573d6000803e3d6000fd5b505050506040513d6020811015610a2657600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a7a57670de0b6b3a76400009050610b5d565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637eeda7036040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d6020811015610b4957600080fd5b810190808051906020019092919050505090505b919050565b610b6a610d6d565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610c2a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610cb0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610d766026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60003390509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a2646970667358221220a51ec0a8bdb76349a7d7c73206b944b4736cb3bbeffb28b4b2ba286c115143c164736f6c634300060c0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000ce100000000000000000000000000000000000000000000000000000000000000003000000000000000000000000765de816845861e75a25fca122bb6898b8b1282a000000000000000000000000d8763cba276a3738e6de85b4b3bf5fded6d6ca73000000000000000000000000e8537a3d056da446677b9e9d6c5db704eaab4787000000000000000000000000000000000000000000000000000000000000000300000000000000000000000067cf66ece8e5ad2d30c1b88c770cde2e3ee811d6000000000000000000000000559ea867fc19798ca167797a02ac4cf3fabf465c0000000000000000000000000a4ff58100a2a0117cc291e375189ccbcb924551

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146102855780639d23d9f2146102b9578063b3596f07146103c6578063f2fde38b1461041e57610088565b80634f568d1f1461008d5780635b6cca80146101d9578063715018a6146102475780637b10399914610251575b600080fd5b6101d7600480360360408110156100a357600080fd5b81019080803590602001906401000000008111156100c057600080fd5b8201836020820111156100d257600080fd5b803590602001918460208302840111640100000000831117156100f457600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f8201169050808301925050505050505091929192908035906020019064010000000081111561015457600080fd5b82018360208201111561016657600080fd5b8035906020019184602083028401116401000000008311171561018857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050509192919290505050610462565b005b61021b600480360360208110156101ef57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610663565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61024f6106cc565b005b610259610852565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61028d610876565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61036f600480360360208110156102cf57600080fd5b81019080803590602001906401000000008111156102ec57600080fd5b8201836020820111156102fe57600080fd5b8035906020019184602083028401116401000000008311171561032057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061089f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103b2578082015181840152602081019050610397565b505050509050019250505060405180910390f35b610408600480360360208110156103dc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610943565b6040518082815260200191505060405180910390f35b6104606004803603602081101561043457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b62565b005b61046a610d6d565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461052a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80518251146105a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f746865207175616e7469747920646f6573206e6f74206d61746368000000000081525060200191505060405180910390fd5b60005b825181101561065e578181815181106105b957fe5b6020026020010151600160008584815181106105d157fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080806001019150506105a4565b505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6106d4610d6d565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610794576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b7f000000000000000000000000000000000000000000000000000000000000ce1081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606080825167ffffffffffffffff811180156108ba57600080fd5b506040519080825280602002602001820160405280156108e95781602001602082028036833780820191505090505b50905060005b83518110156109395761091484828151811061090757fe5b6020026020010151610943565b82828151811061092057fe5b60200260200101818152505080806001019150506108ef565b5080915050919050565b60007f000000000000000000000000000000000000000000000000000000000000ce1073ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156109fc57600080fd5b505afa158015610a10573d6000803e3d6000fd5b505050506040513d6020811015610a2657600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610a7a57670de0b6b3a76400009050610b5d565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637eeda7036040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1f57600080fd5b505afa158015610b33573d6000803e3d6000fd5b505050506040513d6020811015610b4957600080fd5b810190808051906020019092919050505090505b919050565b610b6a610d6d565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610c2a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610cb0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610d766026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60003390509056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a2646970667358221220a51ec0a8bdb76349a7d7c73206b944b4736cb3bbeffb28b4b2ba286c115143c164736f6c634300060c0033