Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- OrocleV1
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 1000
- EVM Version
- default
- Verified at
- 2024-04-01T05:06:28.029289Z
Constructor Arguments
0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c4ffb047c1c6600fc82c68376c502baa72ea20740000000000000000000000004d8ebc5601683c5b50dada3066940e234146c07e
Contract source code
// Sources flattened with hardhat v2.19.4 https://hardhat.org // SPDX-License-Identifier: Apache-2.0 AND MIT // File @openzeppelin/contracts/utils/[email protected] // 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/[email protected] // 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
0x60806040523480156200001157600080fd5b506040516200127c3803806200127c833981016040819052620000349162000172565b6200003f3362000097565b60005b81518110156200008f576200007982828151811062000065576200006562000244565b6020026020010151620000e760201b60201c565b50620000876001826200025a565b905062000042565b505062000282565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155519091907f4c141abccf173677929dea054f218ed87362117834a8869ec9f68d8bdaaea1dc908390a2506001919050565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200016d57600080fd5b919050565b600060208083850312156200018657600080fd5b82516001600160401b03808211156200019e57600080fd5b818501915085601f830112620001b357600080fd5b815181811115620001c857620001c86200013f565b8060051b604051601f19603f83011681018181108582111715620001f057620001f06200013f565b6040529182528482019250838101850191888311156200020f57600080fd5b938501935b828510156200023857620002288562000155565b8452938501939285019262000214565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b808201808211156200027c57634e487b7160e01b600052601160045260246000fd5b92915050565b610fea80620002926000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063943b11b711610097578063ac8a584a11610066578063ac8a584a1461026c578063f2fde38b1461027f578063f3a0721414610292578063ffc79065146102a557600080fd5b8063943b11b7146101bf5780639620d596146101f35780639870d7fe1461022d578063a0d721b61461024057600080fd5b80636d70f7ae116100d35780636d70f7ae14610174578063715018a6146101875780637eed3955146101915780638da5cb5b146101a457600080fd5b8063098c172f146101055780630d9577c61461012b57806359fd3afe1461014e5780635f39ca3c14610161575b600080fd5b610118610113366004610c50565b6102b8565b6040519081526020015b60405180910390f35b61013e610139366004610c99565b610303565b6040519015158152602001610122565b61011861015c366004610d15565b610353565b61013e61016f366004610deb565b6103a0565b61013e610182366004610e37565b6104d9565b61018f6104fc565b005b61013e61019f366004610e59565b610510565b6000546040516001600160a01b039091168152602001610122565b6101d26101cd366004610d15565b610555565b6040805167ffffffffffffffff938416815292909116602083015201610122565b610206610201366004610d15565b61056d565b6040805167ffffffffffffffff948516815293909216602084015290820152606001610122565b61013e61023b366004610e37565b6105c7565b61013e61024e366004610e37565b6001600160a01b031660009081526004602052604090205460ff1690565b61013e61027a366004610e37565b6105da565b61018f61028d366004610e37565b6105ed565b61013e6102a0366004610e95565b61067d565b61013e6102b3366004610c99565b610757565b3360009081526004602052604081205460ff16156102f05760405163388d40c560e21b81523360048201526024015b60405180910390fd5b6102fb8484846107a7565b949350505050565b60008282604051610315929190610ee3565b60405190819003812090859033907f40ed4313298d1d2d91942592748c05d82fea08a3a2336a7379a21c00902dd26090600090a45060019392505050565b3360009081526004602052604081205460ff16156103865760405163388d40c560e21b81523360048201526024016102e7565b60006103928484610861565b5090506102fb8482856107a7565b3360009081526001602052604081205460ff166103d257604051633eaa03e360e01b81523360048201526024016102e7565b600080601884516103e39190610ef3565b15610406578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b84518110156104cc57848101602001517fffffffffffffffff00000000000000000000000000000000000000000000000016925061045761044b826008610f2b565b86016020015160801c90565b6fffffffffffffffffffffffffffffffff16915061047760018484610887565b6104ba5761048785826018610955565b6040517f839af6e60000000000000000000000000000000000000000000000000000000081526004016102e79190610f3e565b6104c5601882610f2b565b9050610409565b506001925050505b919050565b6001600160a01b03811660009081526001602052604081205460ff165b92915050565b610504610a11565b61050e6000610a6b565b565b3360009081526001602052604081205460ff1661054257604051633eaa03e360e01b81523360048201526024016102e7565b61054c8383610ad3565b50600192915050565b6000806105628484610861565b915091509250929050565b336000908152600460205260408120548190819060ff16156105a45760405163388d40c560e21b81523360048201526024016102e7565b6105ae8585610861565b90935091506105be8584866107a7565b90509250925092565b60006105d1610a11565b6104f682610b27565b60006105e4610a11565b6104f682610b7f565b6105f5610a11565b6001600160a01b0381166106715760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102e7565b61067a81610a6b565b50565b3360009081526001602052604081205460ff166106af57604051633eaa03e360e01b81523360048201526024016102e7565b600080603484516106c09190610ef3565b156106e3578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b845181101561074b57848101602001516bffffffffffffffffffffffff1916925061071c610715826014610f2b565b8690610bd1565b9150610729868484610887565b6107395761048785826034610955565b610744603482610f2b565b90506106e6565b50600195945050505050565b60008282604051610769929190610ee3565b60405190819003812090859033907f4bda649efe6b98b0f9c1d5e859c29e20910f45c66dabfe6fad4a4881f7faf9cc90600090a45060019392505050565b6000806107b48584610861565b50905067ffffffffffffffff81166107cd8560ff610f8c565b67ffffffffffffffff1610806107f657508067ffffffffffffffff168467ffffffffffffffff16115b15610839576040517fa74bf46000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016102e7565b505060a09190911b60ff60a01b161760e09190911b1760009081526002602052604090205490565b60e082901b8117600090815260036020526040812054819060c081901c9060801c610562565b6000806108948585610861565b5090506108a2600182610f8c565b9050826002600060a084901b60ff60a01b16871760e089901b17815260200190815260200160002081905550836bffffffffffffffffffffffff19168167ffffffffffffffff168663ffffffff167f59dbccd2127268530ffb2c909067db418e7b6f1ce0453932cd7fde7192e116ee8660405161092191815260200190565b60405180910390a460e085901b8417600090815260036020526040902060c082901b4260801b179055506001949350505050565b82516060906109648385610f2b565b1115610998576109748284610f2b565b845160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b60008267ffffffffffffffff8111156109b3576109b3610d48565b6040519080825280601f01601f1916602001820160405280156109dd576020820181803683370190505b5090508360208601016020820160005b85811015610a055782810151828201526020016109ed565b50919695505050505050565b6000546001600160a01b0316331461050e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102e7565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216600081815260046020526040808220805460ff191685151590811790915590519092917fb59eba7118a2e8b9ad8a512d1bd50724d78f9dbc3c6fcdd8442724f4f10599f891a35050565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155519091907f4c141abccf173677929dea054f218ed87362117834a8869ec9f68d8bdaaea1dc908390a2506001919050565b6001600160a01b038116600081815260016020526040808220805460ff19169055519091907f6b4be2dd49eba45ba43390fbe7da13e2b965d255db41d6a0fcf6d2e15ac1fccb908390a2506001919050565b8151600090610be1836020610f2b565b1115610c1657610bf2826020610f2b565b835160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b50016020015190565b803563ffffffff811681146104d457600080fd5b80356bffffffffffffffffffffffff19811681146104d457600080fd5b600080600060608486031215610c6557600080fd5b610c6e84610c1f565b9250602084013567ffffffffffffffff81168114610c8b57600080fd5b91506105be60408501610c33565b600080600060408486031215610cae57600080fd5b83359250602084013567ffffffffffffffff80821115610ccd57600080fd5b818601915086601f830112610ce157600080fd5b813581811115610cf057600080fd5b876020828501011115610d0257600080fd5b6020830194508093505050509250925092565b60008060408385031215610d2857600080fd5b610d3183610c1f565b9150610d3f60208401610c33565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610d6f57600080fd5b813567ffffffffffffffff80821115610d8a57610d8a610d48565b604051601f8301601f19908116603f01168101908282118183101715610db257610db2610d48565b81604052838152866020858801011115610dcb57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610dfd57600080fd5b813567ffffffffffffffff811115610e1457600080fd5b6102fb84828501610d5e565b80356001600160a01b03811681146104d457600080fd5b600060208284031215610e4957600080fd5b610e5282610e20565b9392505050565b60008060408385031215610e6c57600080fd5b610e7583610e20565b915060208301358015158114610e8a57600080fd5b809150509250929050565b60008060408385031215610ea857600080fd5b610eb183610c1f565b9150602083013567ffffffffffffffff811115610ecd57600080fd5b610ed985828601610d5e565b9150509250929050565b8183823760009101908152919050565b600082610f1057634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b808201808211156104f6576104f6610f15565b600060208083528351808285015260005b81811015610f6b57858101830151858201604001528201610f4f565b506000604082860101526040601f19601f8301168501019250505092915050565b67ffffffffffffffff818116838216019080821115610fad57610fad610f15565b509291505056fea2646970667358221220e4faa56f9e26fef984485f105f5b2b43f4be4b24a815e480a9a49b6cf709f29e64736f6c6343000813003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c4ffb047c1c6600fc82c68376c502baa72ea20740000000000000000000000004d8ebc5601683c5b50dada3066940e234146c07e
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063943b11b711610097578063ac8a584a11610066578063ac8a584a1461026c578063f2fde38b1461027f578063f3a0721414610292578063ffc79065146102a557600080fd5b8063943b11b7146101bf5780639620d596146101f35780639870d7fe1461022d578063a0d721b61461024057600080fd5b80636d70f7ae116100d35780636d70f7ae14610174578063715018a6146101875780637eed3955146101915780638da5cb5b146101a457600080fd5b8063098c172f146101055780630d9577c61461012b57806359fd3afe1461014e5780635f39ca3c14610161575b600080fd5b610118610113366004610c50565b6102b8565b6040519081526020015b60405180910390f35b61013e610139366004610c99565b610303565b6040519015158152602001610122565b61011861015c366004610d15565b610353565b61013e61016f366004610deb565b6103a0565b61013e610182366004610e37565b6104d9565b61018f6104fc565b005b61013e61019f366004610e59565b610510565b6000546040516001600160a01b039091168152602001610122565b6101d26101cd366004610d15565b610555565b6040805167ffffffffffffffff938416815292909116602083015201610122565b610206610201366004610d15565b61056d565b6040805167ffffffffffffffff948516815293909216602084015290820152606001610122565b61013e61023b366004610e37565b6105c7565b61013e61024e366004610e37565b6001600160a01b031660009081526004602052604090205460ff1690565b61013e61027a366004610e37565b6105da565b61018f61028d366004610e37565b6105ed565b61013e6102a0366004610e95565b61067d565b61013e6102b3366004610c99565b610757565b3360009081526004602052604081205460ff16156102f05760405163388d40c560e21b81523360048201526024015b60405180910390fd5b6102fb8484846107a7565b949350505050565b60008282604051610315929190610ee3565b60405190819003812090859033907f40ed4313298d1d2d91942592748c05d82fea08a3a2336a7379a21c00902dd26090600090a45060019392505050565b3360009081526004602052604081205460ff16156103865760405163388d40c560e21b81523360048201526024016102e7565b60006103928484610861565b5090506102fb8482856107a7565b3360009081526001602052604081205460ff166103d257604051633eaa03e360e01b81523360048201526024016102e7565b600080601884516103e39190610ef3565b15610406578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b84518110156104cc57848101602001517fffffffffffffffff00000000000000000000000000000000000000000000000016925061045761044b826008610f2b565b86016020015160801c90565b6fffffffffffffffffffffffffffffffff16915061047760018484610887565b6104ba5761048785826018610955565b6040517f839af6e60000000000000000000000000000000000000000000000000000000081526004016102e79190610f3e565b6104c5601882610f2b565b9050610409565b506001925050505b919050565b6001600160a01b03811660009081526001602052604081205460ff165b92915050565b610504610a11565b61050e6000610a6b565b565b3360009081526001602052604081205460ff1661054257604051633eaa03e360e01b81523360048201526024016102e7565b61054c8383610ad3565b50600192915050565b6000806105628484610861565b915091509250929050565b336000908152600460205260408120548190819060ff16156105a45760405163388d40c560e21b81523360048201526024016102e7565b6105ae8585610861565b90935091506105be8584866107a7565b90509250925092565b60006105d1610a11565b6104f682610b27565b60006105e4610a11565b6104f682610b7f565b6105f5610a11565b6001600160a01b0381166106715760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016102e7565b61067a81610a6b565b50565b3360009081526001602052604081205460ff166106af57604051633eaa03e360e01b81523360048201526024016102e7565b600080603484516106c09190610ef3565b156106e3578351604051637b6d8a9d60e11b81526004016102e791815260200190565b60005b845181101561074b57848101602001516bffffffffffffffffffffffff1916925061071c610715826014610f2b565b8690610bd1565b9150610729868484610887565b6107395761048785826034610955565b610744603482610f2b565b90506106e6565b50600195945050505050565b60008282604051610769929190610ee3565b60405190819003812090859033907f4bda649efe6b98b0f9c1d5e859c29e20910f45c66dabfe6fad4a4881f7faf9cc90600090a45060019392505050565b6000806107b48584610861565b50905067ffffffffffffffff81166107cd8560ff610f8c565b67ffffffffffffffff1610806107f657508067ffffffffffffffff168467ffffffffffffffff16115b15610839576040517fa74bf46000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016102e7565b505060a09190911b60ff60a01b161760e09190911b1760009081526002602052604090205490565b60e082901b8117600090815260036020526040812054819060c081901c9060801c610562565b6000806108948585610861565b5090506108a2600182610f8c565b9050826002600060a084901b60ff60a01b16871760e089901b17815260200190815260200160002081905550836bffffffffffffffffffffffff19168167ffffffffffffffff168663ffffffff167f59dbccd2127268530ffb2c909067db418e7b6f1ce0453932cd7fde7192e116ee8660405161092191815260200190565b60405180910390a460e085901b8417600090815260036020526040902060c082901b4260801b179055506001949350505050565b82516060906109648385610f2b565b1115610998576109748284610f2b565b845160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b60008267ffffffffffffffff8111156109b3576109b3610d48565b6040519080825280601f01601f1916602001820160405280156109dd576020820181803683370190505b5090508360208601016020820160005b85811015610a055782810151828201526020016109ed565b50919695505050505050565b6000546001600160a01b0316331461050e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102e7565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216600081815260046020526040808220805460ff191685151590811790915590519092917fb59eba7118a2e8b9ad8a512d1bd50724d78f9dbc3c6fcdd8442724f4f10599f891a35050565b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155519091907f4c141abccf173677929dea054f218ed87362117834a8869ec9f68d8bdaaea1dc908390a2506001919050565b6001600160a01b038116600081815260016020526040808220805460ff19169055519091907f6b4be2dd49eba45ba43390fbe7da13e2b965d255db41d6a0fcf6d2e15ac1fccb908390a2506001919050565b8151600090610be1836020610f2b565b1115610c1657610bf2826020610f2b565b835160405163abe5c32f60e01b8152600481019290925260248201526044016102e7565b50016020015190565b803563ffffffff811681146104d457600080fd5b80356bffffffffffffffffffffffff19811681146104d457600080fd5b600080600060608486031215610c6557600080fd5b610c6e84610c1f565b9250602084013567ffffffffffffffff81168114610c8b57600080fd5b91506105be60408501610c33565b600080600060408486031215610cae57600080fd5b83359250602084013567ffffffffffffffff80821115610ccd57600080fd5b818601915086601f830112610ce157600080fd5b813581811115610cf057600080fd5b876020828501011115610d0257600080fd5b6020830194508093505050509250925092565b60008060408385031215610d2857600080fd5b610d3183610c1f565b9150610d3f60208401610c33565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610d6f57600080fd5b813567ffffffffffffffff80821115610d8a57610d8a610d48565b604051601f8301601f19908116603f01168101908282118183101715610db257610db2610d48565b81604052838152866020858801011115610dcb57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215610dfd57600080fd5b813567ffffffffffffffff811115610e1457600080fd5b6102fb84828501610d5e565b80356001600160a01b03811681146104d457600080fd5b600060208284031215610e4957600080fd5b610e5282610e20565b9392505050565b60008060408385031215610e6c57600080fd5b610e7583610e20565b915060208301358015158114610e8a57600080fd5b809150509250929050565b60008060408385031215610ea857600080fd5b610eb183610c1f565b9150602083013567ffffffffffffffff811115610ecd57600080fd5b610ed985828601610d5e565b9150509250929050565b8183823760009101908152919050565b600082610f1057634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b808201808211156104f6576104f6610f15565b600060208083528351808285015260005b81811015610f6b57858101830151858201604001528201610f4f565b506000604082860101526040601f19601f8301168501019250505092915050565b67ffffffffffffffff818116838216019080821115610fad57610fad610f15565b509291505056fea2646970667358221220e4faa56f9e26fef984485f105f5b2b43f4be4b24a815e480a9a49b6cf709f29e64736f6c63430008130033