false
false

Contract Address Details

0xFe514492cBFB5b1713C7f7e8fd1c474D2739195f

Contract Name
OrocleV1
Creator
0x10a003–ad5cd4 at 0x2f0d58–85eb3c
Balance
0 OAS
Tokens
Fetching tokens...
Transactions
1,384 Transactions
Transfers
0 Transfers
Gas Used
284,833,630
Last Balance Update
3442029
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
Contract name:
OrocleV1




Optimization enabled
true
Compiler version
v0.8.19+commit.7dd6d404




Optimization runs
1000
EVM Version
default




Verified at
2024-04-17T09:33:31.894731Z

Constructor Arguments

0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000017a5751f3d950eed3bbb07dac191fbd66aa47788000000000000000000000000c644669a3de309e10ce0c7120857b4b2a5555ccd
              

Contract source code

Sol2uml
new
// Sources flattened with hardhat v2.19.4 https://hardhat.org

// SPDX-License-Identifier: Apache-2.0 AND MIT

// File @openzeppelin/contracts/utils/Context.sol@v4.9.5

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}


// File @openzeppelin/contracts/access/Ownable.sol@v4.9.5

// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

/**
 * @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.
 */
abstract 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() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(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");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}


// File contracts/libraries/Bytes.sol

// Original license: SPDX_License_Identifier: Apache-2.0
pragma solidity 0.8.19;

// Index is out of range
error OutOfRange(uint256 requiredLen, uint256 maxLen);

library Bytes {
  // Read address from input bytes buffer
  function readAddress(bytes memory input, uint256 offset) internal pure returns (address result) {
    if (offset + 20 > input.length) {
      revert OutOfRange(offset + 20, input.length);
    }
    assembly {
      result := shr(96, mload(add(add(input, 0x20), offset)))
    }
  }

  // Read unsafe from input bytes buffer
  function readUintUnsafe(bytes memory input, uint256 offset, uint256 bitLen) internal pure returns (uint256 result) {
    assembly {
      result := shr(sub(256, bitLen), mload(add(add(input, 0x20), offset)))
    }
  }

  // Read uint256 from input bytes buffer
  function readUint256(bytes memory input, uint256 offset) internal pure returns (uint256 result) {
    if (offset + 32 > input.length) {
      revert OutOfRange(offset + 32, input.length);
    }
    assembly {
      result := mload(add(add(input, 0x20), offset))
    }
  }

  // Read a sub bytes array from input bytes buffer
  function readBytes(bytes memory input, uint256 offset, uint256 length) internal pure returns (bytes memory) {
    if (offset + length > input.length) {
      revert OutOfRange(offset + length, input.length);
    }
    bytes memory result = new bytes(length);
    assembly {
      // Seek offset to the beginning
      let seek := add(add(input, 0x20), offset)

      // Next is size of data
      let resultOffset := add(result, 0x20)

      for {
        let i := 0
      } lt(i, length) {
        i := add(i, 0x20)
      } {
        mstore(add(resultOffset, i), mload(add(seek, i)))
      }
    }
    return result;
  }
}


// File contracts/orocle-v1/interfaces/IOrocleAggregatorV1.sol

// Original license: SPDX_License_Identifier: Apache-2.0
pragma solidity ^0.8.0;

error ExistedApplication(uint32 appId);
error InvalidApplication(uint32 appId);
error InvalidApplicationName(bytes24 appName);
error InvalidRoundNumber(uint64 round, uint64 requiredRound);
error UndefinedRound(uint64 round);
error InvalidDataLength(uint256 length);
error UnableToPublishData(bytes data);
error DeactivatedUser(address user);

interface IOrocleAggregatorV1 {
  /**
   * Emit event when a new request is created
   * @param identifier Data identifier
   * @param data Data
   */
  function request(uint256 identifier, bytes calldata data) external returns (bool);

  /**
   * Fulfill request
   * @param identifier Data identifier
   * @param data Data
   */
  function fulfill(uint256 identifier, bytes calldata data) external returns (bool);

  /**
   * Check if user is deactivated
   * @param user User address
   * @return status
   */
  function isDeactivated(address user) external view returns (bool);

  /**
   * Get round of a given application
   * @param appId Application ID
   * @return round
   */
  function getMetadata(uint32 appId, bytes20 identifier) external view returns (uint64 round, uint64 lastUpdate);

  /**
   * Get data of an application
   * @param appId Application ID
   * @param round Round number
   * @param identifier Data identifier
   * @return data Data
   */
  function getData(uint32 appId, uint64 round, bytes20 identifier) external view returns (bytes32 data);

  /**
   * Get latest data of an application
   * @param appId Application ID
   * @param identifier Data identifier
   * @return data
   */
  function getLatestData(uint32 appId, bytes20 identifier) external view returns (bytes32 data);

  /**
   * Get latest data of an application
   * @param appId Application ID
   * @param identifier Data identifier
   * @return round lastUpdate data
   */
  function getLatestRound(
    uint32 appId,
    bytes20 identifier
  ) external view returns (uint64 round, uint64 lastUpdate, bytes32 data);
}


// File contracts/orocle-v1/Operatable.sol

// Original license: SPDX_License_Identifier: Apache-2.0
pragma solidity ^0.8.0;

error InvalidOperator(address sender);

contract Operatable {
  mapping(address => bool) private operator;

  event AddOperator(address indexed newOperator);
  event RemoveOperator(address indexed OldOperator);

  modifier onlyOperator() {
    if (!operator[msg.sender]) {
      revert InvalidOperator(msg.sender);
    }
    _;
  }

  function _addOperator(address newOperator) internal returns (bool) {
    operator[newOperator] = true;
    emit AddOperator(newOperator);
    return true;
  }

  function _removeOperator(address oldOperator) internal returns (bool) {
    operator[oldOperator] = false;
    emit RemoveOperator(oldOperator);
    return true;
  }

  function _isOperator(address checkAddress) internal view returns (bool) {
    return operator[checkAddress];
  }

  function isOperator(address checkAddress) external view returns (bool) {
    return _isOperator(checkAddress);
  }
}


// File contracts/orocle-v1/OrocleV1.sol

// Original license: SPDX_License_Identifier: Apache-2.0
pragma solidity ^0.8.0;




contract OrocleV1 is IOrocleAggregatorV1, Ownable, Operatable {
  using Bytes for bytes;

  // Maping unique fingerprint to data
  mapping(bytes32 => bytes32) private database;

  // Mapping application ID ++ identifier to application metadata
  mapping(bytes32 => bytes32) private metadata;

  // Deactivated user
  mapping(address => bool) private deactivated;

  // Publish new data
  event PublishData(uint32 indexed application, uint64 indexed round, bytes20 indexed identifier, bytes32 data);

  // Request new data
  event Request(address indexed actor, uint256 indexed identifier, bytes indexed data);

  // Fulfill request
  event FulFill(address indexed actor, uint256 indexed identifier, bytes indexed data);

  // Deactivated user status update
  event Deactivated(address indexed actor, bool indexed status);

  // Only active user
  modifier onlyActive() {
    if (deactivated[msg.sender]) {
      revert DeactivatedUser(msg.sender);
    }
    _;
  }

  /**
   * Create new oracle
   */
  constructor(address[] memory operatorList) {
    for (uint256 i = 0; i < operatorList.length; i += 1) {
      _addOperator(operatorList[i]);
    }
  }

  //=======================[  External  ]====================

  /**
   * Emit event when a new request is created
   * @param identifier Data identifier
   * @param data Data
   */
  function request(uint256 identifier, bytes calldata data) external returns (bool) {
    emit Request(msg.sender, identifier, data);
    return true;
  }

  /**
   * Fulfill request
   * @param identifier Data identifier
   * @param data Data
   */
  function fulfill(uint256 identifier, bytes calldata data) external returns (bool) {
    emit FulFill(msg.sender, identifier, data);
    return true;
  }

  //=======================[  Owner  ]====================

  /**
   * Set new operator
   * @param newOperator New operator address
   * @return success
   */
  function addOperator(address newOperator) external onlyOwner returns (bool) {
    return _addOperator(newOperator);
  }

  /**
   * Remove old operator
   * @param oldOperator New operator address
   * @return success
   */
  function removeOperator(address oldOperator) external onlyOwner returns (bool) {
    return _removeOperator(oldOperator);
  }

  //=======================[  Operator  ]====================

  // Set deactivated status
  function setDeactivatedStatus(address userAddress, bool status) external onlyOperator returns (bool) {
    _setDeactivateStatus(userAddress, status);
    return true;
  }

  /**
   * Publish data to database
   * @param packedData packed data
   * @return success
   */
  function publishData(uint32 appId, bytes memory packedData) external onlyOperator returns (bool) {
    // Decode appId and chunksize
    bytes20 identifier;
    bytes32 data;
    if (packedData.length % 52 != 0) {
      revert InvalidDataLength(packedData.length);
    }
    for (uint256 i = 0; i < packedData.length; i += 52) {
      identifier = bytes20(uint160(packedData.readUintUnsafe(i, 160)));
      data = bytes32(uint256(packedData.readUint256(i + 20)));
      if (!_publish(appId, identifier, data)) {
        revert UnableToPublishData(packedData.readBytes(i, 52));
      }
    }
    return true;
  }

  // Dedicated function for price
  function publishPrice(bytes memory packedData) external onlyOperator returns (bool) {
    // Decode appId and chunksize
    bytes20 identifier;
    bytes32 data;
    if (packedData.length % 24 != 0) {
      revert InvalidDataLength(packedData.length);
    }
    for (uint256 i = 0; i < packedData.length; i += 24) {
      identifier = bytes20(bytes8(uint64(packedData.readUintUnsafe(i, 64))));
      data = bytes32(uint256(uint128(packedData.readUintUnsafe(i + 8, 128))));
      if (!_publish(1, identifier, data)) {
        revert UnableToPublishData(packedData.readBytes(i, 24));
      }
    }
    return true;
  }

  //=======================[  Interal  ]====================

  // Set deactivated status
  function _setDeactivateStatus(address userAddress, bool status) internal {
    deactivated[userAddress] = status;
    emit Deactivated(userAddress, status);
  }

  // Publish data to Orocle
  function _publish(uint32 appId, bytes20 identifier, bytes32 data) internal returns (bool) {
    (uint64 round, ) = _getMetadata(appId, identifier);
    round += 1;
    // After 255 round, we will reuse the same slot, it saving a lot of gas
    database[_encodeDataKey(appId, round, identifier)] = data;
    emit PublishData(appId, round, identifier, data);
    _setMetadata(appId, identifier, round);
    return true;
  }

  // Set application round
  function _setMetadata(uint32 appId, bytes20 identifier, uint64 round) internal {
    metadata[_encodeRoundKey(appId, identifier)] = _encodeMetadata(round, uint64(block.timestamp));
  }

  //=======================[  Interal View  ]====================

  // Encode data key
  function _encodeDataKey(uint32 appId, uint64 round, bytes20 identifier) internal pure returns (bytes32 dataKey) {
    assembly {
      dataKey := identifier
      dataKey := or(dataKey, shl(160, and(round, 0xff)))
      dataKey := or(dataKey, shl(224, appId))
    }
  }

  // Encode metadata
  function _encodeMetadata(uint64 round, uint64 lastUpdate) internal pure returns (bytes32 dataKey) {
    assembly {
      dataKey := shl(192, round)
      dataKey := or(dataKey, shl(128, lastUpdate))
    }
  }

  // Encode round key
  function _encodeRoundKey(uint32 appId, bytes20 identifier) internal pure returns (bytes32 roundKey) {
    assembly {
      roundKey := identifier
      roundKey := or(roundKey, shl(224, appId))
    }
  }

  // Decode metadata
  function _decodeMetadata(bytes32 metadataRecord) internal pure returns (uint64 round, uint64 lastUpdate) {
    assembly {
      round := shr(192, metadataRecord)
      lastUpdate := shr(128, metadataRecord)
    }
  }

  // Get application round
  function _getMetadata(uint32 appId, bytes20 identifier) internal view returns (uint64 round, uint64 lastUpdate) {
    return _decodeMetadata(metadata[_encodeRoundKey(appId, identifier)]);
  }

  /**
   * Publish data to database
   * @param appId Application ID
   * @param round Round number
   * @param identifier Data identifier
   * @param data Data
   */
  function _readDatabase(uint32 appId, uint64 round, bytes20 identifier) internal view returns (bytes32 data) {
    (uint64 onChainRound, ) = _getMetadata(appId, identifier);
    // Can't get > 255 round in the past
    if (round + 255 < onChainRound || round > onChainRound) {
      revert UndefinedRound(round);
    }
    return database[_encodeDataKey(appId, round, identifier)];
  }

  //=======================[  External View  ]====================

  // Check if user is deactivated
  function isDeactivated(address user) external view returns (bool) {
    return deactivated[user];
  }

  /**
   * Get round of a given application
   * @param appId Application ID
   * @return round
   */
  function getMetadata(uint32 appId, bytes20 identifier) external view returns (uint64 round, uint64 lastUpdate) {
    return _getMetadata(appId, identifier);
  }

  /**
   * Get data of an application
   * @param appId Application ID
   * @param round Round number
   * @param identifier Data identifier
   * @return data Data
   */
  function getData(uint32 appId, uint64 round, bytes20 identifier) external view onlyActive returns (bytes32 data) {
    return _readDatabase(appId, round, identifier);
  }

  /**
   * Get latest data of an application
   * @param appId Application ID
   * @param identifier Data identifier
   * @return data
   */
  function getLatestData(uint32 appId, bytes20 identifier) external view onlyActive returns (bytes32 data) {
    (uint64 round, ) = _getMetadata(appId, identifier);
    data = _readDatabase(appId, round, identifier);
  }

  /**
   * Get latest round and data of an application
   * @param appId Application ID
   * @param identifier Data identifier
   * @return round lastUpdate data
   */
  function getLatestRound(
    uint32 appId,
    bytes20 identifier
  ) external view onlyActive returns (uint64 round, uint64 lastUpdate, bytes32 data) {
    (round, lastUpdate) = _getMetadata(appId, identifier);
    data = _readDatabase(appId, round, identifier);
  }
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address[]","name":"operatorList","internalType":"address[]"}]},{"type":"error","name":"DeactivatedUser","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"error","name":"InvalidDataLength","inputs":[{"type":"uint256","name":"length","internalType":"uint256"}]},{"type":"error","name":"InvalidOperator","inputs":[{"type":"address","name":"sender","internalType":"address"}]},{"type":"error","name":"OutOfRange","inputs":[{"type":"uint256","name":"requiredLen","internalType":"uint256"},{"type":"uint256","name":"maxLen","internalType":"uint256"}]},{"type":"error","name":"UnableToPublishData","inputs":[{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"error","name":"UndefinedRound","inputs":[{"type":"uint64","name":"round","internalType":"uint64"}]},{"type":"event","name":"AddOperator","inputs":[{"type":"address","name":"newOperator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Deactivated","inputs":[{"type":"address","name":"actor","internalType":"address","indexed":true},{"type":"bool","name":"status","internalType":"bool","indexed":true}],"anonymous":false},{"type":"event","name":"FulFill","inputs":[{"type":"address","name":"actor","internalType":"address","indexed":true},{"type":"uint256","name":"identifier","internalType":"uint256","indexed":true},{"type":"bytes","name":"data","internalType":"bytes","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PublishData","inputs":[{"type":"uint32","name":"application","internalType":"uint32","indexed":true},{"type":"uint64","name":"round","internalType":"uint64","indexed":true},{"type":"bytes20","name":"identifier","internalType":"bytes20","indexed":true},{"type":"bytes32","name":"data","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"RemoveOperator","inputs":[{"type":"address","name":"OldOperator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Request","inputs":[{"type":"address","name":"actor","internalType":"address","indexed":true},{"type":"uint256","name":"identifier","internalType":"uint256","indexed":true},{"type":"bytes","name":"data","internalType":"bytes","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"addOperator","inputs":[{"type":"address","name":"newOperator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"fulfill","inputs":[{"type":"uint256","name":"identifier","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"data","internalType":"bytes32"}],"name":"getData","inputs":[{"type":"uint32","name":"appId","internalType":"uint32"},{"type":"uint64","name":"round","internalType":"uint64"},{"type":"bytes20","name":"identifier","internalType":"bytes20"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"data","internalType":"bytes32"}],"name":"getLatestData","inputs":[{"type":"uint32","name":"appId","internalType":"uint32"},{"type":"bytes20","name":"identifier","internalType":"bytes20"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"round","internalType":"uint64"},{"type":"uint64","name":"lastUpdate","internalType":"uint64"},{"type":"bytes32","name":"data","internalType":"bytes32"}],"name":"getLatestRound","inputs":[{"type":"uint32","name":"appId","internalType":"uint32"},{"type":"bytes20","name":"identifier","internalType":"bytes20"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"round","internalType":"uint64"},{"type":"uint64","name":"lastUpdate","internalType":"uint64"}],"name":"getMetadata","inputs":[{"type":"uint32","name":"appId","internalType":"uint32"},{"type":"bytes20","name":"identifier","internalType":"bytes20"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isDeactivated","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOperator","inputs":[{"type":"address","name":"checkAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"publishData","inputs":[{"type":"uint32","name":"appId","internalType":"uint32"},{"type":"bytes","name":"packedData","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"publishPrice","inputs":[{"type":"bytes","name":"packedData","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"removeOperator","inputs":[{"type":"address","name":"oldOperator","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"request","inputs":[{"type":"uint256","name":"identifier","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"setDeactivatedStatus","inputs":[{"type":"address","name":"userAddress","internalType":"address"},{"type":"bool","name":"status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
              

Contract Creation Code

Verify & Publish
0x60806040523480156200001157600080fd5b506040516200127c3803806200127c833981016040819052620000349162000172565b6200003f3362000097565b60005b81518110156200008f576200007982828151811062000065576200006562000244565b6020026020010151620000e760201b60201c565b50620000876001826200025a565b905062000042565b505062000282565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155519091907f4c141abccf173677929dea054f218ed87362117834a8869ec9f68d8bdaaea1dc908390a2506001919050565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200016d57600080fd5b919050565b600060208083850312156200018657600080fd5b82516001600160401b03808211156200019e57600080fd5b818501915085601f830112620001b357600080fd5b815181811115620001c857620001c86200013f565b8060051b604051601f19603f83011681018181108582111715620001f057620001f06200013f565b6040529182528482019250838101850191888311156200020f57600080fd5b938501935b828510156200023857620002288562000155565b8452938501939285019262000214565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b808201808211156200027c57634e487b7160e01b600052601160045260246000fd5b92915050565b610fea80620002926000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063943b11b711610097578063ac8a584a11610066578063ac8a584a1461026c578063f2fde38b1461027f578063f3a0721414610292578063ffc79065146102a557600080fd5b8063943b11b7146101bf5780639620d596146101f35780639870d7fe1461022d578063a0d721b61461024057600080fd5b80636d70f7ae116100d35780636d70f7ae14610174578063715018a6146101875780637eed3955146101915780638da5cb5b146101a457600080fd5b8063098c172f146101055780630d9577c61461012b57806359fd3afe1461014e5780635f39ca3c14610161575b600080fd5b610118610113366004610c50565b6102b8565b6040519081526020015b60405180910390f35b61013e610139366004610c99565b610303565b6040519015158152602001610122565b61011861015c366004610d15565b610353565b61013e61016f366004610deb565b6103a0565b61013e610182366004610e37565b6104d9565b61018f6104fc565b005b61013e61019f366004610e59565b610510565b6000546040516001600160a01b039091168152602001610122565b6101d26101cd366004610d15565b610555565b6040805167ffffffffffffffff938416815292909116602083015201610122565b610206610201366004610d15565b61056d565b6040805167ffffffffffffffff948516815293909216602084015290820152606001610122565b61013e61023b366004610e37565b6105c7565b61013e61024e366004610e37565b6001600160a01b031660009081526004602052604090205460ff1690565b61013e61027a366004610e37565b6105da565b61018f61028d366004610e37565b6105ed565b61013e6102a0366004610e95565b61067d565b61013e6102b3366004610c99565b610757565b3360009081526004602052604081205460ff16156102f05760405163388d40c560e21b81523360048201526024015b60405180910390fd5b6102fb8484846107a7565b949350505050565b60008282604051610315929190610ee3565b60405190819003812090859033907f40ed4313298d1d2d91942592748c05d82fea08a3a2336a7379a21c00902dd26090600090a45060019392505050565b3360009081526004602052604081205460ff16156103865760405163388d40c560e21b81523360048201526024016102e7565b60006103928484610861565b5090506102fb8482856107a7565b3360009081526001602052604081205460ff166103d257604051633eaa03e360e01b81523360048201526024016102e7565b600080601884516103e39190610ef3565b15610406578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b84518110156104cc57848101602001517fffffffffffffffff00000000000000000000000000000000000000000000000016925061045761044b826008610f2b565b86016020015160801c90565b6fffffffffffffffffffffffffffffffff16915061047760018484610887565b6104ba5761048785826018610955565b6040517f839af6e60000000000000000000000000000000000000000000000000000000081526004016102e79190610f3e565b6104c5601882610f2b565b9050610409565b506001925050505b919050565b6001600160a01b03811660009081526001602052604081205460ff165b92915050565b610504610a11565b61050e6000610a6b565b565b3360009081526001602052604081205460ff1661054257604051633eaa03e360e01b81523360048201526024016102e7565b61054c8383610ad3565b50600192915050565b6000806105628484610861565b915091509250929050565b336000908152600460205260408120548190819060ff16156105a45760405163388d40c560e21b81523360048201526024016102e7565b6105ae8585610861565b90935091506105be8584866107a7565b90509250925092565b60006105d1610a11565b6104f682610b27565b60006105e4610a11565b6104f682610b7f565b6105f5610a11565b6001600160a01b0381166106715760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102e7565b61067a81610a6b565b50565b3360009081526001602052604081205460ff166106af57604051633eaa03e360e01b81523360048201526024016102e7565b600080603484516106c09190610ef3565b156106e3578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b845181101561074b57848101602001516bffffffffffffffffffffffff1916925061071c610715826014610f2b565b8690610bd1565b9150610729868484610887565b6107395761048785826034610955565b610744603482610f2b565b90506106e6565b50600195945050505050565b60008282604051610769929190610ee3565b60405190819003812090859033907f4bda649efe6b98b0f9c1d5e859c29e20910f45c66dabfe6fad4a4881f7faf9cc90600090a45060019392505050565b6000806107b48584610861565b50905067ffffffffffffffff81166107cd8560ff610f8c565b67ffffffffffffffff1610806107f657508067ffffffffffffffff168467ffffffffffffffff16115b15610839576040517fa74bf46000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016102e7565b505060a09190911b60ff60a01b161760e09190911b1760009081526002602052604090205490565b60e082901b8117600090815260036020526040812054819060c081901c9060801c610562565b6000806108948585610861565b5090506108a2600182610f8c565b9050826002600060a084901b60ff60a01b16871760e089901b17815260200190815260200160002081905550836bffffffffffffffffffffffff19168167ffffffffffffffff168663ffffffff167f59dbccd2127268530ffb2c909067db418e7b6f1ce0453932cd7fde7192e116ee8660405161092191815260200190565b60405180910390a460e085901b8417600090815260036020526040902060c082901b4260801b179055506001949350505050565b82516060906109648385610f2b565b1115610998576109748284610f2b565b845160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b60008267ffffffffffffffff8111156109b3576109b3610d48565b6040519080825280601f01601f1916602001820160405280156109dd576020820181803683370190505b5090508360208601016020820160005b85811015610a055782810151828201526020016109ed565b50919695505050505050565b6000546001600160a01b0316331461050e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102e7565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216600081815260046020526040808220805460ff191685151590811790915590519092917fb59eba7118a2e8b9ad8a512d1bd50724d78f9dbc3c6fcdd8442724f4f10599f891a35050565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155519091907f4c141abccf173677929dea054f218ed87362117834a8869ec9f68d8bdaaea1dc908390a2506001919050565b6001600160a01b038116600081815260016020526040808220805460ff19169055519091907f6b4be2dd49eba45ba43390fbe7da13e2b965d255db41d6a0fcf6d2e15ac1fccb908390a2506001919050565b8151600090610be1836020610f2b565b1115610c1657610bf2826020610f2b565b835160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b50016020015190565b803563ffffffff811681146104d457600080fd5b80356bffffffffffffffffffffffff19811681146104d457600080fd5b600080600060608486031215610c6557600080fd5b610c6e84610c1f565b9250602084013567ffffffffffffffff81168114610c8b57600080fd5b91506105be60408501610c33565b600080600060408486031215610cae57600080fd5b83359250602084013567ffffffffffffffff80821115610ccd57600080fd5b818601915086601f830112610ce157600080fd5b813581811115610cf057600080fd5b876020828501011115610d0257600080fd5b6020830194508093505050509250925092565b60008060408385031215610d2857600080fd5b610d3183610c1f565b9150610d3f60208401610c33565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610d6f57600080fd5b813567ffffffffffffffff80821115610d8a57610d8a610d48565b604051601f8301601f19908116603f01168101908282118183101715610db257610db2610d48565b81604052838152866020858801011115610dcb57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610dfd57600080fd5b813567ffffffffffffffff811115610e1457600080fd5b6102fb84828501610d5e565b80356001600160a01b03811681146104d457600080fd5b600060208284031215610e4957600080fd5b610e5282610e20565b9392505050565b60008060408385031215610e6c57600080fd5b610e7583610e20565b915060208301358015158114610e8a57600080fd5b809150509250929050565b60008060408385031215610ea857600080fd5b610eb183610c1f565b9150602083013567ffffffffffffffff811115610ecd57600080fd5b610ed985828601610d5e565b9150509250929050565b8183823760009101908152919050565b600082610f1057634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b808201808211156104f6576104f6610f15565b600060208083528351808285015260005b81811015610f6b57858101830151858201604001528201610f4f565b506000604082860101526040601f19601f8301168501019250505092915050565b67ffffffffffffffff818116838216019080821115610fad57610fad610f15565b509291505056fea2646970667358221220e4faa56f9e26fef984485f105f5b2b43f4be4b24a815e480a9a49b6cf709f29e64736f6c634300081300330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000017a5751f3d950eed3bbb07dac191fbd66aa47788000000000000000000000000c644669a3de309e10ce0c7120857b4b2a5555ccd

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063943b11b711610097578063ac8a584a11610066578063ac8a584a1461026c578063f2fde38b1461027f578063f3a0721414610292578063ffc79065146102a557600080fd5b8063943b11b7146101bf5780639620d596146101f35780639870d7fe1461022d578063a0d721b61461024057600080fd5b80636d70f7ae116100d35780636d70f7ae14610174578063715018a6146101875780637eed3955146101915780638da5cb5b146101a457600080fd5b8063098c172f146101055780630d9577c61461012b57806359fd3afe1461014e5780635f39ca3c14610161575b600080fd5b610118610113366004610c50565b6102b8565b6040519081526020015b60405180910390f35b61013e610139366004610c99565b610303565b6040519015158152602001610122565b61011861015c366004610d15565b610353565b61013e61016f366004610deb565b6103a0565b61013e610182366004610e37565b6104d9565b61018f6104fc565b005b61013e61019f366004610e59565b610510565b6000546040516001600160a01b039091168152602001610122565b6101d26101cd366004610d15565b610555565b6040805167ffffffffffffffff938416815292909116602083015201610122565b610206610201366004610d15565b61056d565b6040805167ffffffffffffffff948516815293909216602084015290820152606001610122565b61013e61023b366004610e37565b6105c7565b61013e61024e366004610e37565b6001600160a01b031660009081526004602052604090205460ff1690565b61013e61027a366004610e37565b6105da565b61018f61028d366004610e37565b6105ed565b61013e6102a0366004610e95565b61067d565b61013e6102b3366004610c99565b610757565b3360009081526004602052604081205460ff16156102f05760405163388d40c560e21b81523360048201526024015b60405180910390fd5b6102fb8484846107a7565b949350505050565b60008282604051610315929190610ee3565b60405190819003812090859033907f40ed4313298d1d2d91942592748c05d82fea08a3a2336a7379a21c00902dd26090600090a45060019392505050565b3360009081526004602052604081205460ff16156103865760405163388d40c560e21b81523360048201526024016102e7565b60006103928484610861565b5090506102fb8482856107a7565b3360009081526001602052604081205460ff166103d257604051633eaa03e360e01b81523360048201526024016102e7565b600080601884516103e39190610ef3565b15610406578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b84518110156104cc57848101602001517fffffffffffffffff00000000000000000000000000000000000000000000000016925061045761044b826008610f2b565b86016020015160801c90565b6fffffffffffffffffffffffffffffffff16915061047760018484610887565b6104ba5761048785826018610955565b6040517f839af6e60000000000000000000000000000000000000000000000000000000081526004016102e79190610f3e565b6104c5601882610f2b565b9050610409565b506001925050505b919050565b6001600160a01b03811660009081526001602052604081205460ff165b92915050565b610504610a11565b61050e6000610a6b565b565b3360009081526001602052604081205460ff1661054257604051633eaa03e360e01b81523360048201526024016102e7565b61054c8383610ad3565b50600192915050565b6000806105628484610861565b915091509250929050565b336000908152600460205260408120548190819060ff16156105a45760405163388d40c560e21b81523360048201526024016102e7565b6105ae8585610861565b90935091506105be8584866107a7565b90509250925092565b60006105d1610a11565b6104f682610b27565b60006105e4610a11565b6104f682610b7f565b6105f5610a11565b6001600160a01b0381166106715760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102e7565b61067a81610a6b565b50565b3360009081526001602052604081205460ff166106af57604051633eaa03e360e01b81523360048201526024016102e7565b600080603484516106c09190610ef3565b156106e3578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b845181101561074b57848101602001516bffffffffffffffffffffffff1916925061071c610715826014610f2b565b8690610bd1565b9150610729868484610887565b6107395761048785826034610955565b610744603482610f2b565b90506106e6565b50600195945050505050565b60008282604051610769929190610ee3565b60405190819003812090859033907f4bda649efe6b98b0f9c1d5e859c29e20910f45c66dabfe6fad4a4881f7faf9cc90600090a45060019392505050565b6000806107b48584610861565b50905067ffffffffffffffff81166107cd8560ff610f8c565b67ffffffffffffffff1610806107f657508067ffffffffffffffff168467ffffffffffffffff16115b15610839576040517fa74bf46000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016102e7565b505060a09190911b60ff60a01b161760e09190911b1760009081526002602052604090205490565b60e082901b8117600090815260036020526040812054819060c081901c9060801c610562565b6000806108948585610861565b5090506108a2600182610f8c565b9050826002600060a084901b60ff60a01b16871760e089901b17815260200190815260200160002081905550836bffffffffffffffffffffffff19168167ffffffffffffffff168663ffffffff167f59dbccd2127268530ffb2c909067db418e7b6f1ce0453932cd7fde7192e116ee8660405161092191815260200190565b60405180910390a460e085901b8417600090815260036020526040902060c082901b4260801b179055506001949350505050565b82516060906109648385610f2b565b1115610998576109748284610f2b565b845160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b60008267ffffffffffffffff8111156109b3576109b3610d48565b6040519080825280601f01601f1916602001820160405280156109dd576020820181803683370190505b5090508360208601016020820160005b85811015610a055782810151828201526020016109ed565b50919695505050505050565b6000546001600160a01b0316331461050e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102e7565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216600081815260046020526040808220805460ff191685151590811790915590519092917fb59eba7118a2e8b9ad8a512d1bd50724d78f9dbc3c6fcdd8442724f4f10599f891a35050565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155519091907f4c141abccf173677929dea054f218ed87362117834a8869ec9f68d8bdaaea1dc908390a2506001919050565b6001600160a01b038116600081815260016020526040808220805460ff19169055519091907f6b4be2dd49eba45ba43390fbe7da13e2b965d255db41d6a0fcf6d2e15ac1fccb908390a2506001919050565b8151600090610be1836020610f2b565b1115610c1657610bf2826020610f2b565b835160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b50016020015190565b803563ffffffff811681146104d457600080fd5b80356bffffffffffffffffffffffff19811681146104d457600080fd5b600080600060608486031215610c6557600080fd5b610c6e84610c1f565b9250602084013567ffffffffffffffff81168114610c8b57600080fd5b91506105be60408501610c33565b600080600060408486031215610cae57600080fd5b83359250602084013567ffffffffffffffff80821115610ccd57600080fd5b818601915086601f830112610ce157600080fd5b813581811115610cf057600080fd5b876020828501011115610d0257600080fd5b6020830194508093505050509250925092565b60008060408385031215610d2857600080fd5b610d3183610c1f565b9150610d3f60208401610c33565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610d6f57600080fd5b813567ffffffffffffffff80821115610d8a57610d8a610d48565b604051601f8301601f19908116603f01168101908282118183101715610db257610db2610d48565b81604052838152866020858801011115610dcb57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610dfd57600080fd5b813567ffffffffffffffff811115610e1457600080fd5b6102fb84828501610d5e565b80356001600160a01b03811681146104d457600080fd5b600060208284031215610e4957600080fd5b610e5282610e20565b9392505050565b60008060408385031215610e6c57600080fd5b610e7583610e20565b915060208301358015158114610e8a57600080fd5b809150509250929050565b60008060408385031215610ea857600080fd5b610eb183610c1f565b9150602083013567ffffffffffffffff811115610ecd57600080fd5b610ed985828601610d5e565b9150509250929050565b8183823760009101908152919050565b600082610f1057634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b808201808211156104f6576104f6610f15565b600060208083528351808285015260005b81811015610f6b57858101830151858201604001528201610f4f565b506000604082860101526040601f19601f8301168501019250505092915050565b67ffffffffffffffff818116838216019080821115610fad57610fad610f15565b509291505056fea2646970667358221220e4faa56f9e26fef984485f105f5b2b43f4be4b24a815e480a9a49b6cf709f29e64736f6c63430008130033