Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- EntropyOracle
- Optimization enabled
- false
- Compiler version
- v0.8.24+commit.e11b9ed9
- EVM Version
- Verified at
- 2026-08-25T19:40:46.461488Z
Constructor Arguments
contracts/EntropyOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/Ownable.sol";
import "./AdminZamik.sol";
/**
* @title EntropyOracle
* @notice Collects validator entropy from PulseChain block data
* @dev Uses block.prevrandao (post-merge randomness) + validator signatures
* as entropy sources for ZK circuit inputs
*
* Hardening (v2) — iz varnostnega pregleda (Copilot/Gemini + verifikacija):
* - deauthorizeValidator(): možnost odvzema pooblastila (kompromitiran validator)
* - commitEntropy(): require(entropyHash != 0) — prepreči neveljavne/uninicializirane zapise
* - getEntropy(): bounds check → revert namesto vračanja bytes32(0)
* - dogodki: ValidatorDeauthorized, EntropyMarkedUsed; validator je 'indexed'
* OPOMBA: zaupanje v off-chain validatorja (entropyHash ni on-chain preverjen
* proti block.prevrandao) ostaja po zasnovi. Varnost uporabnika nosi entropija
* 12-besedne kode (pk), ne ta vrednost. Za večjo trust-minimizacijo razmisli o
* mešanju on-chain entropije: keccak256(block.prevrandao, msg.sender, recordCount).
*/
contract EntropyOracle is Ownable, AdminZamik {
struct EntropyRecord {
bytes32 entropyHash;
uint256 blockNumber;
uint256 timestamp;
address validator;
bool used;
}
mapping(uint256 => EntropyRecord) public entropyRecords;
mapping(address => bool) public authorizedValidators;
uint256 public recordCount;
event EntropyCommitted(uint256 indexed recordId, bytes32 entropyHash, address indexed validator);
event ValidatorAuthorized(address indexed validator);
event ValidatorDeauthorized(address indexed validator);
event EntropyMarkedUsed(uint256 indexed recordId);
constructor() Ownable(msg.sender) {}
/**
* @notice Validator commits entropy derived from block randomness
* @dev entropyHash = keccak256(block.prevrandao + validatorSig + nonce)
*/
function commitEntropy(bytes32 entropyHash) external returns (uint256 recordId) {
require(authorizedValidators[msg.sender], "Not authorized validator");
require(entropyHash != bytes32(0), "Zero entropy");
recordId = recordCount++;
entropyRecords[recordId] = EntropyRecord({
entropyHash: entropyHash,
blockNumber: block.number,
timestamp: block.timestamp,
validator: msg.sender,
used: false
});
emit EntropyCommitted(recordId, entropyHash, msg.sender);
}
function getEntropy(uint256 recordId) external view returns (bytes32) {
require(recordId < recordCount, "Invalid record index");
return entropyRecords[recordId].entropyHash;
}
function markUsed(uint256 recordId) external onlyOwner {
require(recordId < recordCount, "Invalid record index");
entropyRecords[recordId].used = true;
emit EntropyMarkedUsed(recordId);
}
/**
* PODELITEV MOCI GRE SKOZI ZAMIK, ODVZEM NE.
*
* Pooblascen validator vnasa entropijo, na kateri slonijo commitmenti.
* Podtaknjen validator je zato napad na sam vir nakljucja — in je viden
* vnaprej, zato javna napoved + zamik.
*
* deauthorizeValidator ostaja takojsen: ob kompromitiranem kljucu je treba
* ukrepati zdaj.
*/
function napoviAuthorizeValidator(address validator) external onlyOwner {
require(validator != address(0), "Zero address");
_napovej(keccak256(abi.encode("authorizeValidator", validator)), "EntropyOracle.authorizeValidator");
}
function authorizeValidator(address validator) external onlyOwner {
require(validator != address(0), "Zero address");
_porabi(keccak256(abi.encode("authorizeValidator", validator)), "EntropyOracle.authorizeValidator");
authorizedValidators[validator] = true;
emit ValidatorAuthorized(validator);
}
/// @notice Odvzame pooblastilo validatorju (npr. ob kompromitaciji ključa).
function deauthorizeValidator(address validator) external onlyOwner {
authorizedValidators[validator] = false;
emit ValidatorDeauthorized(validator);
}
/// @notice Onemogoceno: renounceOwnership() bi trajno onemogocil
/// (de)avtorizacijo validatorjev — oracle bi ostal zamrznjen.
function renounceOwnership() public pure override {
revert("Renounce onemogocen");
}
}
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @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.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @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 {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_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);
}
}
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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;
}
}
contracts/AdminZamik.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title AdminZamik
* @notice Casovni zamik na nevarne admin spremembe.
*
* ZAKAJ TO OBSTAJA
* ----------------
* Owner kljuc na tej platformi NE more krasti: ne more kovati zetonov, ne more
* premikati tujih zetonov in ne more v escrow. Kar PA lahko, je tiho zamenjati
* nastavitve pod nogami uporabnikov — KYC listo, placilni token, prijavljeno
* vrednost sredstva.
*
* Vsi trije so napadi, ki jih je mogoce VIDETI VNAPREJ. Zato jih ne branimo z
* multisigom (ki varuje lastnika kljuca), ampak s casovnim zamikom (ki varuje
* UPORABNIKA): sprememba se mora najprej javno napovedati, sele po zamiku jo je
* mogoce izvesti. Uporabnik ima ves ta cas, da spremembo vidi in izstopi.
*
* Namenoma NI zunanje timelock pogodbe kot lastnika. Tak vzorec doda tveganje
* nedosegljivosti: ce lastniku kdaj ne uspe sestaviti transakcije skozi tujo
* pogodbo, so kontrakti zamrznjeni za vedno. Tu je zamik vgrajen, lastnik pa
* ostane navadna denarnica.
*
* KAJ ZAMIK NE POKRIVA (namerno)
* ------------------------------
* - pause() — zasilna zavora mora biti takojsnja, sicer ni zavora
* - unpause() — vrnitev v obratovanje naj bo hitra
* - odvzem pravice zaustavljalca — ob razkritem kljucu ga moras vreci TAKOJ
* Nevarnost caka, zasilna zavora ne.
*/
abstract contract AdminZamik is Ownable {
/// @notice Rok, v katerem je napoved uporabna. Po njem potece.
/// @dev Brez tega bi stara napoved lezala na verigi kot nabita puska:
/// napoves nekaj neopaznega danes, izvedes cez pol leta, ko nihce vec
/// ne gleda. Napoved, ki ni bila izvedena v roku, je treba ponoviti.
uint256 public constant ROK = 7 days;
/// @notice id napovedi → cas, od katerega je izvedljiva (0 = ni napovedi)
mapping(bytes32 => uint256) public izvedljivoOd;
event SpremembaNapovedana(bytes32 indexed id, string kaj, uint256 izvedljivoOd, uint256 potece);
event SpremembaIzvedena(bytes32 indexed id, string kaj);
event SpremembaPreklicana(bytes32 indexed id, string kaj);
/// @notice Koliko casa mora sprememba cakati.
///
/// ⚠️⚠️ TRENUTNO 10 MINUT — RAZVOJNA VREDNOST ZA TESTNET (943).
/// Nastavljeno 24. 8. 2026 po Juretovi odlocitvi. Projekt se razvija
/// izkljucno na testnetu; mainnet je na pavzi.
///
/// PRED KAKRSNIMKOLI DEPLOYEM NA MAINNET (369) VRNI NA 48 ur.
/// Deset minut zamika na mainnetu pomeni, da napadalec z admin
/// kljucem izvede spremembo, preden jo utegnes opaziti — zamik je
/// takrat videti prisoten, a je brez ucinka.
///
/// @dev virtual ostaja, da lahko posamezna pogodba vrednost se povozi
/// (MarketplaceTestnet to pocne).
function zamik() public view virtual returns (uint256) {
return 10 minutes;
}
// ── Notranje ────────────────────────────────────────────────────────────
/// @dev id MORA vsebovati tocne parametre spremembe, sicer bi lahko
/// napovedal nedolzno vrednost in izvedel skodljivo.
function _napovej(bytes32 id, string memory kaj) internal {
require(izvedljivoOd[id] == 0, "Ze napovedano");
uint256 od = block.timestamp + zamik();
izvedljivoOd[id] = od;
emit SpremembaNapovedana(id, kaj, od, od + ROK);
}
function _porabi(bytes32 id, string memory kaj) internal {
uint256 od = izvedljivoOd[id];
require(od != 0, "Ni napovedano");
require(block.timestamp >= od, "Zamik se ni potekel");
require(block.timestamp <= od + ROK, "Napoved je potekla");
delete izvedljivoOd[id];
emit SpremembaIzvedena(id, kaj);
}
// ── Javno ───────────────────────────────────────────────────────────────
/// @notice Preklic napovedane spremembe. Takojsen — premisliti se mora biti
/// mogoce hitreje, kot se izvede.
function prekliciSpremembo(bytes32 id, string calldata kaj) external onlyOwner {
require(izvedljivoOd[id] != 0, "Ni napovedano");
delete izvedljivoOd[id];
emit SpremembaPreklicana(id, kaj);
}
/// @notice Stanje napovedi — da ga stran in nadzorni sistem lahko prikazeta.
function stanjeNapovedi(bytes32 id)
external
view
returns (bool napovedana, uint256 od, uint256 potece, bool izvedljivaZdaj)
{
uint256 t = izvedljivoOd[id];
if (t == 0) return (false, 0, 0, false);
return (true, t, t + ROK, block.timestamp >= t && block.timestamp <= t + ROK);
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"event","name":"EntropyCommitted","inputs":[{"type":"uint256","name":"recordId","internalType":"uint256","indexed":true},{"type":"bytes32","name":"entropyHash","internalType":"bytes32","indexed":false},{"type":"address","name":"validator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"EntropyMarkedUsed","inputs":[{"type":"uint256","name":"recordId","internalType":"uint256","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":"SpremembaIzvedena","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32","indexed":true},{"type":"string","name":"kaj","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"SpremembaNapovedana","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32","indexed":true},{"type":"string","name":"kaj","internalType":"string","indexed":false},{"type":"uint256","name":"izvedljivoOd","internalType":"uint256","indexed":false},{"type":"uint256","name":"potece","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SpremembaPreklicana","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32","indexed":true},{"type":"string","name":"kaj","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"ValidatorAuthorized","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ValidatorDeauthorized","inputs":[{"type":"address","name":"validator","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"ROK","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"authorizeValidator","inputs":[{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"authorizedValidators","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"recordId","internalType":"uint256"}],"name":"commitEntropy","inputs":[{"type":"bytes32","name":"entropyHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deauthorizeValidator","inputs":[{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"entropyHash","internalType":"bytes32"},{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"address","name":"validator","internalType":"address"},{"type":"bool","name":"used","internalType":"bool"}],"name":"entropyRecords","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getEntropy","inputs":[{"type":"uint256","name":"recordId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"izvedljivoOd","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"markUsed","inputs":[{"type":"uint256","name":"recordId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"napoviAuthorizeValidator","inputs":[{"type":"address","name":"validator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"prekliciSpremembo","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"},{"type":"string","name":"kaj","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"recordCount","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"napovedana","internalType":"bool"},{"type":"uint256","name":"od","internalType":"uint256"},{"type":"uint256","name":"potece","internalType":"uint256"},{"type":"bool","name":"izvedljivaZdaj","internalType":"bool"}],"name":"stanjeNapovedi","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"zamik","inputs":[]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610d8c806100a56000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c8063900407bc116100a2578063c75021c911610071578063c75021c91461024d578063d48693d1146102cc578063e826f69a146102d4578063f2fde38b146102de578063f55c7f7c146102f157600080fd5b8063900407bc1461020b57806398c1d49514610214578063a978237714610227578063bd7b358c1461023a57600080fd5b806374e6a469116100de57806374e6a4691461019357806376e382c8146101a6578063776528cd146101b95780638da5cb5b146101f057600080fd5b80630854eef51461011057806327401ca5146101435780635871416314610158578063715018a61461018b575b600080fd5b61013061011e366004610b5f565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b610156610151366004610b5f565b610304565b005b61017b610166366004610b78565b60036020526000908152604090205460ff1681565b604051901515815260200161013a565b6101566103a5565b6101306101a1366004610b5f565b6103e3565b6101566101b4366004610ba8565b610440565b6101cc6101c7366004610b5f565b6104e7565b6040805194151585526020850193909352918301521515606082015260800161013a565b6000546040516001600160a01b03909116815260200161013a565b61013060045481565b610156610222366004610b78565b610554565b610130610235366004610b5f565b6105a5565b610156610248366004610b78565b61071c565b61029961025b366004610b5f565b60026020819052600091825260409091208054600182015492820154600390920154909291906001600160a01b03811690600160a01b900460ff1685565b604080519586526020860194909452928401919091526001600160a01b031660608301521515608082015260a00161013a565b610258610130565b61013062093a8081565b6101566102ec366004610b78565b61081a565b6101566102ff366004610b78565b610858565b61030c61090a565b60045481106103595760405162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e4cac6dee4c840d2dcc8caf60631b60448201526064015b60405180910390fd5b600081815260026020526040808220600301805460ff60a01b1916600160a01b1790555182917faf9b44b01fc5355a968be2e584466c01fe6111b5b4cf0e8025476f8016c3b48491a250565b60405162461bcd60e51b81526020600482015260136024820152722932b737bab731b29037b732b6b7b3b7b1b2b760691b6044820152606401610350565b6000600454821061042d5760405162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e4cac6dee4c840d2dcc8caf60631b6044820152606401610350565b5060009081526002602052604090205490565b61044861090a565b60008381526001602052604081205490036104955760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b6044820152606401610350565b600083815260016020526040808220919091555183907f72003eda7c2c39777210bccbf69141a92bbe56d746914a16f5ee3aaf5e6f7a83906104da9085908590610c24565b60405180910390a2505050565b6000818152600160205260408120548190819081908082036105175760008060008094509450945094505061054d565b60018161052762093a8082610c69565b834210158015610543575061053f62093a8085610c69565b4211155b9450945094509450505b9193509193565b61055c61090a565b6001600160a01b038116600081815260036020526040808220805460ff19169055517f24677e89c1354f05a4ade2790aa316e609a07ac84922dbf78df5610c1067372a9190a250565b3360009081526003602052604081205460ff166106045760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a65642076616c696461746f7200000000000000006044820152606401610350565b816106405760405162461bcd60e51b815260206004820152600c60248201526b5a65726f20656e74726f707960a01b6044820152606401610350565b6004805490600061065083610c82565b909155506040805160a081018252848152436020808301918252428385019081523360608501818152600060808701818152898252600295869052908890209651875594516001870155915192850192909255516003909301805492511515600160a01b026001600160a81b03199093166001600160a01b0394909416939093179190911790915590519192509082907f710a66ed585920488d2abacc385b3d111de06b0f51f11fb9030f305c511dd9129061070f9086815260200190565b60405180910390a3919050565b61072461090a565b6001600160a01b0381166107695760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610350565b6107ce8160405160200161077d9190610c9b565b604051602081830303815290604052805190602001206040518060400160405280602081526020017f456e74726f70794f7261636c652e617574686f72697a6556616c696461746f72815250610939565b6001600160a01b038116600081815260036020526040808220805460ff19166001179055517f7e7b46f96b81fdc950459cd1b69e84ba6672783d48c4626c47822c844eae56959190a250565b61082261090a565b6001600160a01b03811661084c57604051631e4fbdf760e01b815260006004820152602401610350565b61085581610a62565b50565b61086061090a565b6001600160a01b0381166108a55760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610350565b610855816040516020016108b99190610c9b565b604051602081830303815290604052805190602001206040518060400160405280602081526020017f456e74726f70794f7261636c652e617574686f72697a6556616c696461746f72815250610ab2565b6000546001600160a01b031633146109375760405163118cdaa760e01b8152336004820152602401610350565b565b600082815260016020526040812054908190036109885760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b6044820152606401610350565b804210156109ce5760405162461bcd60e51b815260206004820152601360248201527216985b5a5ac81cd9481b9a481c1bdd195ad95b606a1b6044820152606401610350565b6109db62093a8082610c69565b421115610a1f5760405162461bcd60e51b81526020600482015260126024820152714e61706f766564206a6520706f74656b6c6160701b6044820152606401610350565b600083815260016020526040808220919091555183907ffac4537038ebc9eaa00d86a88a6c2e268012d306f6442966aab36014a1954323906104da908590610d1e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008281526001602052604090205415610afe5760405162461bcd60e51b815260206004820152600d60248201526c5a65206e61706f766564616e6f60981b6044820152606401610350565b6000610b0c61025842610c69565b60008481526001602052604090208190559050827f63a0d065f46e07e30a4f246d28eb53f839982100439173db92dbd5700ab37c158383610b5062093a8082610c69565b6040516104da93929190610d31565b600060208284031215610b7157600080fd5b5035919050565b600060208284031215610b8a57600080fd5b81356001600160a01b0381168114610ba157600080fd5b9392505050565b600080600060408486031215610bbd57600080fd5b83359250602084013567ffffffffffffffff80821115610bdc57600080fd5b818601915086601f830112610bf057600080fd5b813581811115610bff57600080fd5b876020828501011115610c1157600080fd5b6020830194508093505050509250925092565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c7c57610c7c610c53565b92915050565b600060018201610c9457610c94610c53565b5060010190565b60408082526012908201527130baba3437b934bd32ab30b634b230ba37b960711b60608201526001600160a01b0391909116602082015260800190565b6000815180845260005b81811015610cfe57602081850181015186830182015201610ce2565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610ba16020830184610cd8565b606081526000610d446060830186610cd8565b6020830194909452506040015291905056fea2646970667358221220eef7d2cf9cfe984b1d1360717b81b2c573d31a04a5e21507f0779505bfd5199564736f6c63430008180033
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061010b5760003560e01c8063900407bc116100a2578063c75021c911610071578063c75021c91461024d578063d48693d1146102cc578063e826f69a146102d4578063f2fde38b146102de578063f55c7f7c146102f157600080fd5b8063900407bc1461020b57806398c1d49514610214578063a978237714610227578063bd7b358c1461023a57600080fd5b806374e6a469116100de57806374e6a4691461019357806376e382c8146101a6578063776528cd146101b95780638da5cb5b146101f057600080fd5b80630854eef51461011057806327401ca5146101435780635871416314610158578063715018a61461018b575b600080fd5b61013061011e366004610b5f565b60016020526000908152604090205481565b6040519081526020015b60405180910390f35b610156610151366004610b5f565b610304565b005b61017b610166366004610b78565b60036020526000908152604090205460ff1681565b604051901515815260200161013a565b6101566103a5565b6101306101a1366004610b5f565b6103e3565b6101566101b4366004610ba8565b610440565b6101cc6101c7366004610b5f565b6104e7565b6040805194151585526020850193909352918301521515606082015260800161013a565b6000546040516001600160a01b03909116815260200161013a565b61013060045481565b610156610222366004610b78565b610554565b610130610235366004610b5f565b6105a5565b610156610248366004610b78565b61071c565b61029961025b366004610b5f565b60026020819052600091825260409091208054600182015492820154600390920154909291906001600160a01b03811690600160a01b900460ff1685565b604080519586526020860194909452928401919091526001600160a01b031660608301521515608082015260a00161013a565b610258610130565b61013062093a8081565b6101566102ec366004610b78565b61081a565b6101566102ff366004610b78565b610858565b61030c61090a565b60045481106103595760405162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e4cac6dee4c840d2dcc8caf60631b60448201526064015b60405180910390fd5b600081815260026020526040808220600301805460ff60a01b1916600160a01b1790555182917faf9b44b01fc5355a968be2e584466c01fe6111b5b4cf0e8025476f8016c3b48491a250565b60405162461bcd60e51b81526020600482015260136024820152722932b737bab731b29037b732b6b7b3b7b1b2b760691b6044820152606401610350565b6000600454821061042d5760405162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e4cac6dee4c840d2dcc8caf60631b6044820152606401610350565b5060009081526002602052604090205490565b61044861090a565b60008381526001602052604081205490036104955760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b6044820152606401610350565b600083815260016020526040808220919091555183907f72003eda7c2c39777210bccbf69141a92bbe56d746914a16f5ee3aaf5e6f7a83906104da9085908590610c24565b60405180910390a2505050565b6000818152600160205260408120548190819081908082036105175760008060008094509450945094505061054d565b60018161052762093a8082610c69565b834210158015610543575061053f62093a8085610c69565b4211155b9450945094509450505b9193509193565b61055c61090a565b6001600160a01b038116600081815260036020526040808220805460ff19169055517f24677e89c1354f05a4ade2790aa316e609a07ac84922dbf78df5610c1067372a9190a250565b3360009081526003602052604081205460ff166106045760405162461bcd60e51b815260206004820152601860248201527f4e6f7420617574686f72697a65642076616c696461746f7200000000000000006044820152606401610350565b816106405760405162461bcd60e51b815260206004820152600c60248201526b5a65726f20656e74726f707960a01b6044820152606401610350565b6004805490600061065083610c82565b909155506040805160a081018252848152436020808301918252428385019081523360608501818152600060808701818152898252600295869052908890209651875594516001870155915192850192909255516003909301805492511515600160a01b026001600160a81b03199093166001600160a01b0394909416939093179190911790915590519192509082907f710a66ed585920488d2abacc385b3d111de06b0f51f11fb9030f305c511dd9129061070f9086815260200190565b60405180910390a3919050565b61072461090a565b6001600160a01b0381166107695760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610350565b6107ce8160405160200161077d9190610c9b565b604051602081830303815290604052805190602001206040518060400160405280602081526020017f456e74726f70794f7261636c652e617574686f72697a6556616c696461746f72815250610939565b6001600160a01b038116600081815260036020526040808220805460ff19166001179055517f7e7b46f96b81fdc950459cd1b69e84ba6672783d48c4626c47822c844eae56959190a250565b61082261090a565b6001600160a01b03811661084c57604051631e4fbdf760e01b815260006004820152602401610350565b61085581610a62565b50565b61086061090a565b6001600160a01b0381166108a55760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b6044820152606401610350565b610855816040516020016108b99190610c9b565b604051602081830303815290604052805190602001206040518060400160405280602081526020017f456e74726f70794f7261636c652e617574686f72697a6556616c696461746f72815250610ab2565b6000546001600160a01b031633146109375760405163118cdaa760e01b8152336004820152602401610350565b565b600082815260016020526040812054908190036109885760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b6044820152606401610350565b804210156109ce5760405162461bcd60e51b815260206004820152601360248201527216985b5a5ac81cd9481b9a481c1bdd195ad95b606a1b6044820152606401610350565b6109db62093a8082610c69565b421115610a1f5760405162461bcd60e51b81526020600482015260126024820152714e61706f766564206a6520706f74656b6c6160701b6044820152606401610350565b600083815260016020526040808220919091555183907ffac4537038ebc9eaa00d86a88a6c2e268012d306f6442966aab36014a1954323906104da908590610d1e565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008281526001602052604090205415610afe5760405162461bcd60e51b815260206004820152600d60248201526c5a65206e61706f766564616e6f60981b6044820152606401610350565b6000610b0c61025842610c69565b60008481526001602052604090208190559050827f63a0d065f46e07e30a4f246d28eb53f839982100439173db92dbd5700ab37c158383610b5062093a8082610c69565b6040516104da93929190610d31565b600060208284031215610b7157600080fd5b5035919050565b600060208284031215610b8a57600080fd5b81356001600160a01b0381168114610ba157600080fd5b9392505050565b600080600060408486031215610bbd57600080fd5b83359250602084013567ffffffffffffffff80821115610bdc57600080fd5b818601915086601f830112610bf057600080fd5b813581811115610bff57600080fd5b876020828501011115610c1157600080fd5b6020830194508093505050509250925092565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610c7c57610c7c610c53565b92915050565b600060018201610c9457610c94610c53565b5060010190565b60408082526012908201527130baba3437b934bd32ab30b634b230ba37b960711b60608201526001600160a01b0391909116602082015260800190565b6000815180845260005b81811015610cfe57602081850181015186830182015201610ce2565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000610ba16020830184610cd8565b606081526000610d446060830186610cd8565b6020830194909452506040015291905056fea2646970667358221220eef7d2cf9cfe984b1d1360717b81b2c573d31a04a5e21507f0779505bfd5199564736f6c63430008180033