false
false
100

Contract Address Details

0xDdF7F5d1233F56a8f2c86F952C079BcD52877890

Contract Name
WitnetPriceFeed
Creator
0x0da617ā€“1b94d7 at 0xf01e3dā€“429f62
Balance
0 KAVA ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
11601964
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
WitnetPriceFeed




Optimization enabled
true
Compiler version
v0.7.6+commit.7338295f




Optimization runs
200
EVM Version
istanbul




Verified at
2023-04-19T17:06:52.152844Z

Constructor Arguments

000000000000000000000000d39d4d972c7e166856c4eb29e54d3548b4597f534c80cf2e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000015180

Arg [0] (address) : 0xd39d4d972c7e166856c4eb29e54d3548b4597f53
Arg [1] (bytes4) : 4c80cf2e
Arg [2] (uint256) : 6
Arg [3] (uint256) : 86400

              

Contract source code

// Sources flattened with hardhat v2.14.0 https://hardhat.org

// File contracts/dependencies/openzeppelin/contracts/SafeMath.sol

// SPDX-License-Identifier: agpl-3.0, MIT
pragma solidity 0.7.6;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
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;
  }
}


// File contracts/interfaces/IERC2362.sol


pragma solidity 0.7.6;

interface IERC2362
{
	/**
	 * @dev Exposed function pertaining to EIP standards
	 * @param _id bytes32 ID of the query
	 * @return int,uint,uint returns the value, timestamp, and status code of query
	 */
	function valueFor(bytes32 _id) external view returns(int256,uint256,uint256);
}


// File contracts/interfaces/IPriceFeed.sol


pragma solidity 0.7.6;

interface IPriceFeed {
  // --- Function ---
  function fetchPrice() external view returns (uint256);

  function updatePrice() external returns (uint256);
}


// File contracts/misc/WitnetPriceFeed.sol


pragma solidity 0.7.6;



/*
 * The WitnetPriceFeed uses Witnet as primary oracle.
 */
contract WitnetPriceFeed is IPriceFeed {
  using SafeMath for uint256;

  uint256 public constant DECIMAL_PRECISION = 1e18;

  IERC2362 public oracle;
  bytes4 public erc2362id;
  uint256 public decimals;

  // Use to convert a price answer to an 18-digit precision uint
  uint256 public constant TARGET_DIGITS = 18;

  // Maximum time period allowed since Witnet's latest round data timestamp, beyond which Witnet is considered frozen.
  // For stablecoins we recommend 90000, as Witnet updates once per day when there is no significant price movement
  // For volatile assets we recommend 14400 (4 hours)
  uint256 public immutable TIMEOUT;

  // Maximum deviation allowed between two consecutive Witnet oracle prices. 18-digit precision.
  uint256 public constant MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND = 5e17; // 50%

  /*
   * The maximum relative price difference between two oracle responses allowed in order for the PriceFeed
   * to return to using the Witnet oracle. 18-digit precision.
   */
  uint256 public constant MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES = 5e16; // 5%

  // The last good price seen from an oracle by Liquity
  uint256 public lastGoodPrice;

  struct OracleResponse {
    uint256 answer;
    uint256 timestamp;
    bool success;
  }

  enum Status {
    oracleWorking,
    oracleUntrusted
  }

  // The current status of the PricFeed, which determines the conditions for the next price fetch attempt
  Status public status;

  event LastGoodPriceUpdated(uint256 _lastGoodPrice);
  event PriceFeedStatusChanged(Status newStatus);

  // --- Dependency setters ---

  constructor(IERC2362 _oracle, bytes4 _erc2362id, uint256 _decimals, uint256 _timeout) {
    oracle = _oracle;
    erc2362id = _erc2362id;
    decimals = _decimals;
    TIMEOUT = _timeout;

    // Explicitly set initial system status
    status = Status.oracleWorking;

    // Get an initial price from Witnet to serve as first reference for lastGoodPrice
    OracleResponse memory response = _getCurrentResponse();

    require(
      !_oracleIsBroken(response) &&
        block.timestamp.sub(response.timestamp) < _timeout,
      'PriceFeed: Witnet must be working and current'
    );

    lastGoodPrice = _scalePriceByDigits(uint256(response.answer), decimals);
  }

  // --- Functions ---

  /*
   * fetchPrice():
   * Returns the latest price obtained from the Oracle. Called by Liquity functions that require a current price.
   *
   * Also callable by anyone externally.
   *
   * Non-view function - it stores the last good price seen by Liquity.
   *
   * Uses a main oracle (Witnet). If it fails,
   * it uses the last good price seen by Liquity.
   *
   */
  function fetchPrice() external view override returns (uint256) {
    (, uint256 price) = _fetchPrice();
    return price;
  }

  function updatePrice() external override returns (uint256) {
    (Status newStatus, uint256 price) = _fetchPrice();
    lastGoodPrice = price;
    if (status != newStatus) {
      status = newStatus;
      emit PriceFeedStatusChanged(newStatus);
    }
    return price;
  }

  function _fetchPrice() internal view returns (Status, uint256) {
    // Get current and previous price data from Witnet, and current price data from Band
    OracleResponse memory response = _getCurrentResponse();

    // --- CASE 1: System fetched last price from Witnet  ---
    if (status == Status.oracleWorking) {
      // If Witnet is broken or frozen
      if (_oracleIsBroken(response) || _oracleIsFrozen(response)) {
        // If Witnet is broken, switch to Band and return current Band price
        return (Status.oracleUntrusted, lastGoodPrice);
      }

      // If Witnet is working, return Witnet current price (no status change)
      return (Status.oracleWorking, response.answer);
    }

    // --- CASE 2: Witnet oracle is untrusted at the last price fetch ---
    if (status == Status.oracleUntrusted) {
      if (_oracleIsBroken(response) || _oracleIsFrozen(response)) {
        return (Status.oracleUntrusted, lastGoodPrice);
      }

      return (Status.oracleWorking, response.answer);
    }
  }

  // --- Helper functions ---

  /* Witnet is considered broken if its current or previous round data is in any way bad. We check the previous round
   * for two reasons:
   *
   * 1) It is necessary data for the price deviation check in case 1,
   * and
   * 2) Witnet is the PriceFeed's preferred primary oracle - having two consecutive valid round responses adds
   * peace of mind when using or returning to Witnet.
   */
  function _oracleIsBroken(OracleResponse memory _response) internal view returns (bool) {
    // Check for response call reverted
    if (!_response.success) {
      return true;
    }
    // Check for an invalid timeStamp that is 0, or in the future
    if (_response.timestamp == 0 || _response.timestamp > block.timestamp) {
      return true;
    }
    // Check for non-positive price (original value returned from Witnet is int256)
    if (int256(_response.answer) <= 0) {
      return true;
    }

    return false;
  }

  function _oracleIsFrozen(OracleResponse memory _response) internal view returns (bool) {
    return block.timestamp.sub(_response.timestamp) > TIMEOUT;
  }

  function _scalePriceByDigits(uint256 _price, uint256 _digits)
    internal
    pure
    returns (uint256)
  {
    /*
     * Convert the price returned by the Witnet oracle to an 18-digit decimal for use by Liquity.
     * At date of Liquity launch, Witnet uses an 8-digit price, but we also handle the possibility of
     * future changes.
     */
    uint256 price;
    if (_digits >= TARGET_DIGITS) {
      // Scale the returned price value down to Liquity's target precision
      price = _price.div(10**(_digits - TARGET_DIGITS));
    } else if (_digits < TARGET_DIGITS) {
      // Scale the returned price value up to Liquity's target precision
      price = _price.mul(10**(TARGET_DIGITS - _digits));
    }
    return price;
  }

  // --- Oracle response wrapper functions ---

  function _getCurrentResponse()
    internal
    view
    returns (OracleResponse memory response)
  {
    // Secondly, try to get latest price data:
    try oracle.valueFor(erc2362id) returns (
      int256 lastPrice,
      uint256 lastTimestamp,
      uint256 /* latestUpdateStatus */
    ) {
      // If call to Witnet succeeds, return the response and success = true
      response.answer = _scalePriceByDigits(uint256(lastPrice), decimals);
      response.timestamp = lastTimestamp;
      response.success = true;
      return response;
    } catch {
      // If call to Witnet aggregator reverts, return a zero response with success = false
      return response;
    }
  }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_oracle","internalType":"contract IERC2362"},{"type":"bytes4","name":"_erc2362id","internalType":"bytes4"},{"type":"uint256","name":"_decimals","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"LastGoodPriceUpdated","inputs":[{"type":"uint256","name":"_lastGoodPrice","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"PriceFeedStatusChanged","inputs":[{"type":"uint8","name":"newStatus","internalType":"enum WitnetPriceFeed.Status","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DECIMAL_PRECISION","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"TARGET_DIGITS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"TIMEOUT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"erc2362id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"fetchPrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastGoodPrice","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC2362"}],"name":"oracle","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"enum WitnetPriceFeed.Status"}],"name":"status","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"updatePrice","inputs":[]}]
              

Contract Creation Code

0x60a06040523480156200001157600080fd5b5060405162000c8038038062000c80833981810160405260808110156200003757600080fd5b50805160208201516040830151606090930151600080546001600160a01b0319166001600160a01b0385161763ffffffff60a01b1916600160a01b60e085901c02178155600185905560808290526003805460ff19169055929391926200009d62000131565b9050620000aa8162000203565b158015620000d4575081620000d28260200151426200025860201b620002b71790919060201c565b105b620001115760405162461bcd60e51b815260040180806020018281038252602d81526020018062000c32602d913960400191505060405180910390fd5b8051600154620001229190620002ab565b60025550620004e09350505050565b6200013b620004bd565b6000546040805163f78eea8360e01b81526001600160e01b0319600160a01b840460e01b16600482015290516001600160a01b039092169163f78eea8391602480820192606092909190829003018186803b1580156200019a57600080fd5b505afa925050508015620001d057506040513d6060811015620001bc57600080fd5b508051602082015160409092015190919060015b620001db5762000200565b620001ef83600154620002ab60201b60201c565b845250602083015250600160408201525b90565b60008160400151620002185750600162000253565b602082015115806200022d5750428260200151115b156200023c5750600162000253565b81516000126200024f5750600162000253565b5060005b919050565b6000620002a283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506200031160201b60201c565b90505b92915050565b60008060128310620002df57620002d760128403600a0a85620003ac60201b620003021790919060201c565b9050620002a2565b6012831015620002a2576200030983601203600a0a85620003f660201b620003441790919060201c565b949350505050565b60008184841115620003a45760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015620003685781810151838201526020016200034e565b50505050905090810190601f168015620003965780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000620002a283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506200045460201b60201c565b6000826200040757506000620002a5565b828202828482816200041557fe5b0414620002a25760405162461bcd60e51b815260040180806020018281038252602181526020018062000c5f6021913960400191505060405180910390fd5b60008183620004a65760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315620003685781810151838201526020016200034e565b506000838581620004b357fe5b0495945050505050565b604051806060016040528060008152602001600081526020016000151581525090565b6080516107326200050060003980610295528061063652506107326000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c806358a6aa881161007157806358a6aa881461011c578063673a7e28146101245780637dc0d1d01461012c578063a20baee614610150578063efac30df14610158578063f56f48f21461017d576100b4565b80630490be83146100b95780630fdb11cf146100d35780631be5c92f146100db578063200d2ed2146100e3578063313ce5671461010c57806345079cb414610114575b600080fd5b6100c1610185565b60408051918252519081900360200190f35b6100c161018b565b6100c161019e565b6100eb6101a3565b604051808260018111156100fb57fe5b815260200191505060405180910390f35b6100c16101ac565b6100c16101b2565b6100c16101bd565b6100c16101c9565b610134610268565b604080516001600160a01b039092168252519081900360200190f35b6100c1610277565b610160610283565b604080516001600160e01b03199092168252519081900360200190f35b6100c1610293565b60025481565b60008061019661039d565b925050505b90565b601281565b60035460ff1681565b60015481565b66b1a2bc2ec5000081565b6706f05b59d3b2000081565b60008060006101d661039d565b600281905590925090508160018111156101ec57fe5b60035460ff1660018111156101fd57fe5b14610262576003805483919060ff19166001838181111561021a57fe5b02179055507f5c57579a8214fe4f710c1c56fa829f045b9fa6d225a744225a30c32188064d4e826040518082600181111561025157fe5b815260200191505060405180910390a15b91505090565b6000546001600160a01b031681565b670de0b6b3a764000081565b600054600160a01b900460e01b81565b7f000000000000000000000000000000000000000000000000000000000000000081565b60006102f983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610424565b90505b92915050565b60006102f983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506104bb565b600082610353575060006102fc565b8282028284828161036057fe5b04146102f95760405162461bcd60e51b81526004018080602001828103825260218152602001806106dc6021913960400191505060405180910390fd5b60008060006103aa610520565b9050600060035460ff1660018111156103bf57fe5b14156103fc576103ce816105e4565b806103dd57506103dd81610632565b156103f057505060025460019150610420565b51600092509050610420565b600160035460ff16600181111561040f57fe5b141561041e576103ce816105e4565b505b9091565b600081848411156104b35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610478578181015183820152602001610460565b50505050905090810190601f1680156104a55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000818361050a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610478578181015183820152602001610460565b50600083858161051657fe5b0495945050505050565b6105286106b8565b6000546040805163f78eea8360e01b81526001600160e01b0319600160a01b840460e01b16600482015290516001600160a01b039092169163f78eea8391602480820192606092909190829003018186803b15801561058657600080fd5b505afa9250505080156105ba57506040513d60608110156105a657600080fd5b508051602082015160409092015190919060015b6105c35761019b565b6105cf83600154610673565b8452506020830152506001604082015261019b565b600081604001516105f75750600161062d565b6020820151158061060b5750428260200151115b156106185750600161062d565b81516000126106295750600161062d565b5060005b919050565b60007f000000000000000000000000000000000000000000000000000000000000000061066c8360200151426102b790919063ffffffff16565b1192915050565b600080601283106106965761068f846011198501600a0a610302565b90506102f9565b60128310156102f9576106b0846012859003600a0a610344565b949350505050565b60405180606001604052806000815260200160008152602001600015158152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212209f9e53197789bb5bf625443e882176c9432d8e333af100d9d0db9cc5bf71395364736f6c634300070600335072696365466565643a205769746e6574206d75737420626520776f726b696e6720616e642063757272656e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77000000000000000000000000d39d4d972c7e166856c4eb29e54d3548b4597f534c80cf2e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000015180

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100b45760003560e01c806358a6aa881161007157806358a6aa881461011c578063673a7e28146101245780637dc0d1d01461012c578063a20baee614610150578063efac30df14610158578063f56f48f21461017d576100b4565b80630490be83146100b95780630fdb11cf146100d35780631be5c92f146100db578063200d2ed2146100e3578063313ce5671461010c57806345079cb414610114575b600080fd5b6100c1610185565b60408051918252519081900360200190f35b6100c161018b565b6100c161019e565b6100eb6101a3565b604051808260018111156100fb57fe5b815260200191505060405180910390f35b6100c16101ac565b6100c16101b2565b6100c16101bd565b6100c16101c9565b610134610268565b604080516001600160a01b039092168252519081900360200190f35b6100c1610277565b610160610283565b604080516001600160e01b03199092168252519081900360200190f35b6100c1610293565b60025481565b60008061019661039d565b925050505b90565b601281565b60035460ff1681565b60015481565b66b1a2bc2ec5000081565b6706f05b59d3b2000081565b60008060006101d661039d565b600281905590925090508160018111156101ec57fe5b60035460ff1660018111156101fd57fe5b14610262576003805483919060ff19166001838181111561021a57fe5b02179055507f5c57579a8214fe4f710c1c56fa829f045b9fa6d225a744225a30c32188064d4e826040518082600181111561025157fe5b815260200191505060405180910390a15b91505090565b6000546001600160a01b031681565b670de0b6b3a764000081565b600054600160a01b900460e01b81565b7f000000000000000000000000000000000000000000000000000000000001518081565b60006102f983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610424565b90505b92915050565b60006102f983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506104bb565b600082610353575060006102fc565b8282028284828161036057fe5b04146102f95760405162461bcd60e51b81526004018080602001828103825260218152602001806106dc6021913960400191505060405180910390fd5b60008060006103aa610520565b9050600060035460ff1660018111156103bf57fe5b14156103fc576103ce816105e4565b806103dd57506103dd81610632565b156103f057505060025460019150610420565b51600092509050610420565b600160035460ff16600181111561040f57fe5b141561041e576103ce816105e4565b505b9091565b600081848411156104b35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610478578181015183820152602001610460565b50505050905090810190601f1680156104a55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000818361050a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610478578181015183820152602001610460565b50600083858161051657fe5b0495945050505050565b6105286106b8565b6000546040805163f78eea8360e01b81526001600160e01b0319600160a01b840460e01b16600482015290516001600160a01b039092169163f78eea8391602480820192606092909190829003018186803b15801561058657600080fd5b505afa9250505080156105ba57506040513d60608110156105a657600080fd5b508051602082015160409092015190919060015b6105c35761019b565b6105cf83600154610673565b8452506020830152506001604082015261019b565b600081604001516105f75750600161062d565b6020820151158061060b5750428260200151115b156106185750600161062d565b81516000126106295750600161062d565b5060005b919050565b60007f000000000000000000000000000000000000000000000000000000000001518061066c8360200151426102b790919063ffffffff16565b1192915050565b600080601283106106965761068f846011198501600a0a610302565b90506102f9565b60128310156102f9576106b0846012859003600a0a610344565b949350505050565b60405180606001604052806000815260200160008152602001600015158152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212209f9e53197789bb5bf625443e882176c9432d8e333af100d9d0db9cc5bf71395364736f6c63430007060033