Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- RWATokenFactory
- Optimization enabled
- false
- Compiler version
- v0.8.24+commit.e11b9ed9
- EVM Version
- Verified at
- 2026-09-07T09:45:09.328086Z
Constructor Arguments
000000000000000000000000cf59b47b780a73ee10aeea21a81dfc3cb70b9c88000000000000000000000000f119beb1b343e46c4ed0e78362cd3f87e87ef4cc00000000000000000000000050555531d7a9ae79a5ad9100f114def88c6691d9000000000000000000000000d37d29526d271770f42c2553faae7f282effc1630000000000000000000000005a5db3d01a38d640a81182b1769a9f1e4d1f0f7400000000000000000000000016eeba545a07a88cdf21cfdde973ee67cdc32000
Arg [0] (address) : 0xcf59b47b780a73ee10aeea21a81dfc3cb70b9c88
Arg [1] (address) : 0xf119beb1b343e46c4ed0e78362cd3f87e87ef4cc
Arg [2] (address) : 0x50555531d7a9ae79a5ad9100f114def88c6691d9
Arg [3] (address) : 0xd37d29526d271770f42c2553faae7f282effc163
Arg [4] (address) : 0x5a5db3d01a38d640a81182b1769a9f1e4d1f0f74
Arg [5] (address) : 0x16eeba545a07a88cdf21cfdde973ee67cdc32000
contracts/RWATokenFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/access/Ownable.sol";
import "./RWAToken.sol";
interface IZKVerifierRegistracija {
function registrirajZeton(address zeton) external;
}
interface IUORSRegister {
function authorizedUORS(address operater) external view returns (bool);
}
/**
* @title RWATokenFactory
* @notice Postavi po en ERC-20 zeton za VSAKO realno sredstvo.
*
* EN ZETON NA SREDSTVO
* Vsako sredstvo ima svojo ERC-20 pogodbo. Deleži razlicnih sredstev tako niso
* medsebojno zamenljivi in je vrednost (`assetValueUSD`) lastnost posameznega
* sredstva, ne skupna vsem. Locitev je na verigi in je z metapodatki ni mogoce
* nadomestiti.
*
* ZAKAJ TOVARNA IN NE ROCNA POSTAVITEV
* Postavitev zetona zahteva vec zaporednih korakov (nastavitev prejemnika
* provizij in KYC seznama, prenos lastnistva, registracija pri ZKVerifierju).
* Tovarna jih opravi v eni transakciji, zato delno izveden postopek ni mogoc.
*
* KAJ TOVARNA NE POCNE
* Ne kuje zetonov. Ti nastanejo izkljucno prek ZK dokaza v ZKVerifierju;
* tovarna ustvari le pogodbo brez zaloge.
*/
contract RWATokenFactory is Ownable {
address public immutable zkVerifier;
address public immutable entropyOracle;
// ─────────────────────────────────────────────────────────────────────────
// KDO SME USTVARITI SREDSTVO
//
// Sredstvo sme ustvariti izkljucno pooblasceni UORS operater (overitelj), ne
// lastnik te pogodbe. Ustvaritev je izjava, da dolocen predmet obstaja, je
// ocenjen in ima lastnika; to preverjanje opravi overitelj.
//
// Lastnik pogodbe ni v poti nastanka niti kot sopodpisnik — sicer bi bil
// soizdajatelj in odgovornost za vsebino izjave bi bila deljena.
// ─────────────────────────────────────────────────────────────────────────
address public immutable uors; // UORSRegistry
/// Skupne nastavitve, ki jih dobi vsak nov zeton.
address public feeRecipient;
address public kyc;
address[] public sredstva;
mapping(address => bool) public jeNase;
event SredstvoUstvarjeno(
address indexed zeton,
string ime,
string simbol,
uint256 vrednostUSD,
string metapodatkiCID
);
event NastavitveSpremenjene(address feeRecipient, address kyc);
modifier samoUORS() {
require(IUORSRegister(uors).authorizedUORS(msg.sender), "Samo UORS operater");
_;
}
constructor(
address _zkVerifier,
address _entropyOracle,
address _feeRecipient,
address _kyc,
address _lastnik,
address _uors
) Ownable(_lastnik) {
require(_zkVerifier != address(0), "ZKVerifier je nujen");
require(_feeRecipient != address(0), "feeRecipient je nujen");
require(_lastnik != address(0), "Lastnik je nujen");
require(_uors != address(0), "UORSRegistry je nujen");
uors = _uors;
zkVerifier = _zkVerifier;
entropyOracle = _entropyOracle;
feeRecipient = _feeRecipient;
kyc = _kyc;
}
/**
* @notice Ustvari novo sredstvo — en zeton, ena stvar iz resnicnega sveta.
* @dev Vsako sredstvo je zavesten podpis lastnika. Za regulirano dejavnost je
* to prednost, ne ovira: namerno dejanje na sredstvo je bolje kot tiho
* dodajanje v skupno posodo.
*/
function ustvariSredstvo(
string calldata ime,
string calldata simbol,
string calldata metapodatkiCID,
uint256 vrednostUSD
) external samoUORS returns (address zeton) {
require(bytes(ime).length != 0, "Ime je nujno");
require(bytes(simbol).length != 0, "Simbol je nujen");
require(vrednostUSD != 0, "Vrednost je nujna");
zeton = address(new RWAToken(NastavitveZetona({
ime: ime,
simbol: simbol,
metapodatkiCID: metapodatkiCID,
vrednostUSD: vrednostUSD,
zkVerifier: zkVerifier,
entropyOracle: entropyOracle,
feeRecipient: feeRecipient,
kyc: kyc,
lastnik: owner(), // lastnik zetona = lastnik tovarne (Ledger / multisig)
uors: uors, // zamrznitev sredstva sme SAMO UORS (glej RWAToken)
// Overitelj je TISTI operater, ki sredstvo ustvarja zdaj. Zapise se
// nespremenljivo in doloca, kdo sme pozneje spremeniti cenitev —
// odgovornost za izjavo o vrednosti nosi tisti, ki jo je dal.
overitelj: msg.sender
})));
sredstva.push(zeton);
jeNase[zeton] = true;
// Sele s tem sme ZKVerifier kovati na tem zetonu.
IZKVerifierRegistracija(zkVerifier).registrirajZeton(zeton);
emit SredstvoUstvarjeno(zeton, ime, simbol, vrednostUSD, metapodatkiCID);
}
/// @notice Spremeni nastavitve za PRIHODNJE zetone. Ze ustvarjenih ne dotakne —
/// tam se feeRecipient in kyc spreminjata na zetonu samem, pod zamikom.
function nastavi(address _feeRecipient, address _kyc) external onlyOwner {
require(_feeRecipient != address(0), "feeRecipient je nujen");
feeRecipient = _feeRecipient;
kyc = _kyc;
emit NastavitveSpremenjene(_feeRecipient, _kyc);
}
function steviloSredstev() external view returns (uint256) {
return sredstva.length;
}
/// @notice Vsa sredstva naenkrat — stran jih rabi za seznam zetonov.
function vsaSredstva() external view returns (address[] memory) {
return sredstva;
}
/// @notice Onemogoceno: brez lastnika tovarna ne bi mogla vec ustvariti sredstva.
function renounceOwnership() public pure override {
revert("Renounce onemogocen");
}
}
@openzeppelin/contracts/interfaces/draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-721.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
@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/token/ERC20/ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* Both values are immutable: they can only be set once during construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/// @inheritdoc IERC20
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/// @inheritdoc IERC20
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/// @inheritdoc IERC20
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}
@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity >=0.6.2;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
@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 PulseChain mainnet. Edina veriga, kjer zamik varuje pravo vrednost.
uint256 internal constant MAINNET = 369;
/// @notice Koliko casa mora napovedana sprememba cakati, preden je izvedljiva.
///
/// mainnet (369) 48 ur imetnik ima cas spremembo videti in izstopiti
/// druge verige 10 minut razvojno okolje
///
/// @dev Vrednost doloca `block.chainid`, ne nastavitev ob postavitvi. Ista
/// bajtna koda tako na produkcijski verigi vedno vrne 48 ur; razvojne
/// vrednosti ni mogoce prenesti na mainnet, niti pomotoma.
/// @dev `virtual` zato, da lahko posamezna testna pogodba vrednost povozi.
function zamik() public view virtual returns (uint256) {
return block.chainid == MAINNET ? 48 hours : 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);
}
}
contracts/RWAToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./AdminZamik.sol";
interface IKYCWhitelist {
function isWhitelisted(address account) external view returns (bool);
}
interface IUORSRegistry {
function authorizedUORS(address operater) external view returns (bool);
}
/**
* @title RWAToken
* @notice PRC-20 token representing a Real World Asset on PulseChain
* @dev Backed by verified off-chain data stored on IPFS.
* Minting requires a valid ZK proof from ZKVerifier.
* Transfer fee: 0.5% ob vsakem transferu → feeRecipient (platforma).
*
* OPCIJSKA KYC transfer-restrikcija (permissioned token):
* - če je `kyc` nastavljen (!= address(0)), morata biti POŠILJATELJ in
* PREJEMNIK na KYC beli listi (izjeme: mint, burn, fee-leg na feeRecipient).
* - To prepreči, da bi RWA pristal na nepreverjeni denarnici (zahteva, ki jo
* regulacija običajno postavlja finančnim instrumentom — MiFID II/ZTFI-1).
* - POMEMBNO: naslov Marketplace pogodbe (escrow listingov/ponudb) mora biti
* na beli listi, sicer list()/buy()/acceptOffer() padejo.
* - Privzeto IZKLOPLJENO (kyc == address(0)) → navaden prosto-prenosljiv ERC-20.
*/
/**
* @notice Nastavitve novega zetona v ENI strukturi.
* @dev Ne zaradi lepote: devet locenih parametrov konstruktorja je tovarno
* pognalo v "stack too deep" (Groth16 assembly + `new` z devetimi argumenti).
* Struktura gre v pomnilnik namesto na sklad.
*/
struct NastavitveZetona {
string ime;
string simbol;
string metapodatkiCID;
uint256 vrednostUSD;
address zkVerifier;
address entropyOracle;
address feeRecipient; // NIKOLI privzeto msg.sender — glej opombo pri konstruktorju
address kyc; // 0x0 = brez omejitve, a mora biti napisano izrecno
address lastnik;
address uors; // UORSRegistry — kdo sme sredstvo zamrzniti (glej spodaj)
address overitelj; // UORS operater, ki je sredstvo overil — glej `samoOveritelj`
}
contract RWAToken is ERC20, Ownable, AdminZamik {
string public assetMetadataCID;
uint256 public assetValueUSD;
address public zkVerifier;
address public entropyOracle;
// --- Provizije ---
uint256 public constant TRANSFER_FEE_BPS = 50; // 0,5% = 50 basis points
address public feeRecipient; // prejemnik provizij (platforma)
// ── Kdo je sredstvo overil ─────────────────────────────────────────────────
//
// Cenitev sme spremeniti SAMO ta naslov. Cenitev je izjava o vrednosti
// tujega premozenja in doloca ceno prve prodaje; odgovornost zanjo nosi
// tisti overitelj, ki je sredstvo overil, ne katerikoli drug.
//
// Zapise ga tovarna ob nastanku (`msg.sender` v `ustvariSredstvo`), zato je
// `immutable`: naknadno ga ne more prestaviti nihce, tudi lastnik ne.
address public immutable overitelj;
// ── Prvotni lastnik in enkratnost kovanja ─────────────────────────────────
//
// `prvotniLastnik` je naslov, ki je prejel prvo (in edino) kovanje tega
// sredstva. Trznica iz njega izpelje, ali je oglas PRIMARNI: primarna je
// prodaja tistega, ki je sredstvo dobil ob tokenizaciji, in samo zanjo velja
// omejitev, da mora biti cena enaka overjeni cenitvi. Ce bi to zastavico
// vpisoval prodajalec sam, bi bila omejitev obvod z enim argumentom.
//
// Vrednost `address(0)` pomeni "se ni skovano" in hkrati sluzi kot kljucavnica:
// kovanje je mogoce natanko enkrat. Enkratnost ni kozmetika — cena na primarnem
// trgu je `cenitev / stevilo enot`, zato bi vsako naknadno kovanje tiho premaknilo
// razmerje "ena enota = 1/N sredstva" vsem dosedanjim imetnikom.
address public prvotniLastnik;
// Dovoljenje za en sam `mintFee`, ki sledi kovanju. Ni javno: je notranje
// stanje ene transakcije, ne podatek o sredstvu.
bool private provizijaOdprta;
// --- KYC transfer-restrikcija (opcijska) ---
address public kyc; // KYCWhitelist; če address(0), je restrikcija IZKLOPLJENA
// ─────────────────────────────────────────────────────────────────────────
// ZAPORA PRENOSA — varovalo za kupca
//
// Kovanje v denarnico lastnika sredstva je takojsnje; PRENOS komurkoli
// drugemu (in s tem oglas na trznici) je mogoc sele po `aktivenOd`.
// V tem oknu je sredstvo javno vidno in ga je mogoce ustaviti, preden je
// prenosljivo tretji osebi.
//
// Omejitev je v zetonu, ne v Marketplaceu: neposreden `transfer` iz
// denarnice bi jo sicer obsel.
//
// ⚠️ Dolzino zapore doloca VERIGA, ne clovek — enako kot `zamik()`:
// na produkcijski verigi 48 ur, drugod 10 minut, z ISTO bajtno kodo.
// Prej je bila `constant` 48 ur povsod, kar je na testnetu pomenilo dvodnevno
// cakanje pri vsakem preizkusu. Fiksna vrednost, ki bi jo bilo treba pred
// produkcijo rocno vrniti, bi bila zanasanje na spomin: tako je nihce ne more
// skrajsati in nihce je ne more pozabiti prestaviti nazaj.
//
// ⚠️ Ime NI ZAPORA_PRENOSA (velike crke): vrednost ni konstanta, ker je odvisna
// od verige. Ime, ki obljublja konstanto, bi bilo napacno poimenovana stevilka.
// ─────────────────────────────────────────────────────────────────────────
function _zaporaPrenosa() internal view returns (uint256) {
return block.chainid == MAINNET ? 48 hours : 10 minutes;
}
/// @notice Koliko casa po nastanku sredstvo se ni prenosljivo. Bere ga stran,
/// da lahko pove pravo stevilko na pravi verigi.
function zaporaPrenosa() external view returns (uint256) {
return _zaporaPrenosa();
}
uint256 public immutable aktivenOd;
// ─────────────────────────────────────────────────────────────────────────
// ZAMRZNITEV — pravico ima izkljucno pooblasceni UORS operater
//
// Obstoj sredstva potrdi UORS, zato je tudi preklic v njegovi pristojnosti.
// Lastnik (admin) tega zetona ne more zamrzniti; s tem bi presojal o
// posameznem sredstvu in prevzel del odgovornosti, ki je pri UORS.
//
// Posledica, ki je del zasnove: admin posameznega sredstva ne more ustaviti.
// Njegova pot je sistemska — odvzem pooblastila operaterju in `pause()` na
// ZKVerifierju oziroma Marketplaceu.
// ─────────────────────────────────────────────────────────────────────────
address public immutable uors; // UORSRegistry
bool public zamrznjen;
event Zamrznjeno(address indexed kdo);
event Odmrznjeno(address indexed kdo);
mapping(bytes32 => bool) public usedProofs;
// Dogodka za spremembo opisa ni: `assetMetadataCID` je nespremenljiv.
/// @notice Sprememba prijavljene vrednosti sredstva; oddana ob vsaki spremembi,
/// da je razvidna iz dnevnika verige in ne le iz stanja pogodbe.
event AssetValueUpdated(uint256 newValueUSD);
event TokensMinted(address indexed to, uint256 amount, bytes32 proofHash);
/// @notice Zapisan prvotni lastnik — iz njega trznica izpelje primarni oglas.
event PrvotniLastnikZapisan(address indexed lastnik);
event TransferFeeCollected(address indexed from, address indexed to, uint256 fee);
event FeeRecipientUpdated(address indexed newRecipient);
event KycUpdated(address indexed newKyc);
/**
* @notice `feeRecipient`, `kyc` in `lastnik` se nastavijo v konstruktorju,
* ne po postavitvi.
* @dev Nobena od teh vrednosti nima privzetka: `feeRecipient` in `lastnik`
* sta obvezna (`require` spodaj), `kyc` pa je lahko `address(0)` samo,
* ce je to izrecno podano. Zeton brez KYC omejitve je s tem zavestna
* izbira ob postavitvi in ne posledica neizvedenega naknadnega koraka.
*/
constructor(NastavitveZetona memory n)
ERC20(n.ime, n.simbol)
Ownable(n.lastnik)
{
require(n.zkVerifier != address(0), "ZKVerifier je nujen");
require(n.feeRecipient != address(0), "feeRecipient je nujen");
require(n.lastnik != address(0), "Lastnik je nujen");
assetMetadataCID = n.metapodatkiCID;
assetValueUSD = n.vrednostUSD;
zkVerifier = n.zkVerifier;
entropyOracle = n.entropyOracle;
feeRecipient = n.feeRecipient;
kyc = n.kyc; // sme biti 0x0, a mora biti napisano izrecno
uors = n.uors; // sme biti 0x0 samo v testih; tovarna ga vedno poda
overitelj = n.overitelj; // 0x0 pomeni: cenitve ne more spremeniti nihce
aktivenOd = block.timestamp + _zaporaPrenosa();
}
modifier samoUORS() {
require(uors != address(0) && IUORSRegistry(uors).authorizedUORS(msg.sender),
"Samo UORS operater");
_;
}
/**
* @dev Samo TISTI overitelj, ki je sredstvo overil — in samo dokler je se
* pooblascen. Odvzem pooblastila mu pravico takoj vzame; skrbnik s tem
* obdrzi veto, ne da bi dobil moznost cenitev spremeniti sam.
*
* ⚠️ Trije LOCENI razlogi, ne en skupen: bralec mora vedeti, ali sredstvo
* overitelja nima, ali ga ima in to ni on, ali pa mu je bilo pooblastilo
* odvzeto. Nevednost in prepoved nista isto.
*/
modifier samoOveritelj() {
require(overitelj != address(0), "Sredstvo nima zapisanega overitelja");
require(msg.sender == overitelj, "Samo overitelj tega sredstva");
require(uors != address(0) && IUORSRegistry(uors).authorizedUORS(msg.sender),
"Overitelj ni vec pooblascen");
_;
}
/// @notice Ali je sredstvo mogoce prenasati (in s tem prodajati).
/// @dev Namenjeno strani, da lahko pove RAZLOG in odstevanje, namesto da
/// uporabnik dobi golo revertirano transakcijo brez pojasnila.
function jePrenosMogoc() external view returns (bool mogoc, uint256 odKdaj, bool zamrznjeno) {
return (block.timestamp >= aktivenOd && !zamrznjen, aktivenOd, zamrznjen);
}
/// @notice Zamrzne prenose tega sredstva. Takojsno — nevarnost ne caka.
function zamrzni() external samoUORS {
zamrznjen = true;
emit Zamrznjeno(msg.sender);
}
/// @notice Odmrzne. Prav tako samo UORS: kdor je odgovoren za izjavo, jo tudi
/// umakne in vrne.
function odmrzni() external samoUORS {
zamrznjen = false;
emit Odmrznjeno(msg.sender);
}
/**
* @notice Mintanje prek ZKVerifier (brez transfer fee — to je kreacija tokenov).
*/
function mintWithProof(address to, uint256 amount, bytes32 proofHash) external {
require(msg.sender == zkVerifier, "Only ZK verifier");
require(!usedProofs[proofHash], "Proof already used");
// Sredstvo se skuje natanko enkrat. Brez te omejitve bi lahko overitelj
// registriral novo kodo za isti zeton in obtok bi zrasel — s tem bi se
// razmerje "ena enota = 1/N sredstva" in primarna cena premaknila vsem.
require(prvotniLastnik == address(0), "Sredstvo je ze skovano");
usedProofs[proofHash] = true;
prvotniLastnik = to;
provizijaOdprta = true;
_mint(to, amount);
emit TokensMinted(to, amount, proofHash);
emit PrvotniLastnikZapisan(to);
}
/**
* @notice Mintanje provizije ob tokenizaciji — pokliče samo ZKVerifier.
* @dev Brez usedProofs check — fee mint ne porabi proof.
*/
function mintFee(address to, uint256 amount) external {
require(msg.sender == zkVerifier, "Only ZK verifier");
require(to != address(0), "Zero address");
// Provizija sme nastati samo takoj za kovanjem in samo enkrat. Brez tega
// bi bila enkratnost kovanja odvisna od tega, kako se vede DRUGA pogodba
// (ZKVerifier), namesto da bi jo ta pogodba zagotavljala sama.
require(provizijaOdprta, "Provizija brez kovanja");
provizijaOdprta = false;
_mint(to, amount);
}
/**
* @notice Override _update: ob vsakem transferu (ne mint/burn) zaračuna 0,5% fee.
* @dev OZ v5 uporablja _update namesto _transfer/_beforeTokenTransfer.
* Fee se ne zaračuna pri: mint (from==0), burn (to==0),
* feeRecipient transakcijah (izogne se loop-u).
*/
function _update(address from, address to, uint256 amount) internal override {
bool isMint = (from == address(0));
bool isBurn = (to == address(0));
// --- KYC transfer-restrikcija (opcijska; aktivna le če kyc != address(0)) ---
if (kyc != address(0)) {
// Prejemnik mora biti preverjen (izjema: burn in fee-leg na feeRecipient).
if (!isBurn && to != feeRecipient) {
require(IKYCWhitelist(kyc).isWhitelisted(to), "Prejemnik ni KYC preverjen");
}
// Pošiljatelj mora biti preverjen (izjema: mint in feeRecipient).
if (!isMint && from != feeRecipient) {
require(IKYCWhitelist(kyc).isWhitelisted(from), "Posiljatelj ni KYC preverjen");
}
}
// --- Zapora prenosa in zamrznitev ---
// Mint (from == 0) je dovoljen takoj: lastnik sredstva ni ogrozen, ker
// nihce se nicesar ni placal. Vse ostalo caka na aktivacijo.
if (!isMint) {
require(!zamrznjen, "Sredstvo je zamrznjeno");
require(block.timestamp >= aktivenOd, "Sredstvo se ni aktivno za prenos");
}
// Mint, burn ali fee-related prenos → brez dodatnega fee
if (isMint || isBurn || from == feeRecipient || to == feeRecipient) {
super._update(from, to, amount);
return;
}
uint256 fee = amount * TRANSFER_FEE_BPS / 10_000;
uint256 net = amount - fee;
super._update(from, feeRecipient, fee); // 0,5% → platforma
super._update(from, to, net); // 99,5% → prejemnik
emit TransferFeeCollected(from, to, fee);
}
// --- Admin ---
// Vse spodnje spremembe tecejo prek javne napovedi in casovnega zamika
// (glej AdminZamik.sol). Imetnik zetona tako vsako spremembo vidi priti in
// ima cas izstopiti — namesto da se zbudi v drugacen instrument.
/// @notice Nastavi KYCWhitelist za transfer-restrikcijo. address(0) = izklopljeno.
/// @dev POZOR: ob vklopu mora biti naslov Marketplace pogodbe na beli listi (escrow).
function napoviSetKyc(address _kyc) external onlyOwner {
_napovej(keccak256(abi.encode("setKyc", _kyc)), "RWAToken.setKyc");
}
function setKyc(address _kyc) external onlyOwner {
_porabi(keccak256(abi.encode("setKyc", _kyc)), "RWAToken.setKyc");
kyc = _kyc;
emit KycUpdated(_kyc);
}
function napoviSetFeeRecipient(address _feeRecipient) external onlyOwner {
require(_feeRecipient != address(0), "Zero address");
_napovej(keccak256(abi.encode("setFeeRecipient", _feeRecipient)), "RWAToken.setFeeRecipient");
}
function setFeeRecipient(address _feeRecipient) external onlyOwner {
require(_feeRecipient != address(0), "Zero address");
_porabi(keccak256(abi.encode("setFeeRecipient", _feeRecipient)), "RWAToken.setFeeRecipient");
feeRecipient = _feeRecipient;
emit FeeRecipientUpdated(_feeRecipient);
}
// ── Metapodatki (opis sredstva na IPFS) so NESPREMENLJIVI ──────────────────
//
// `assetMetadataCID` se nastavi ob postavitvi in ga ne more spremeniti nihce —
// ne lastnik in ne UORS operater; funkcije za to ni. Imetnik zato bere isti
// opis, na podlagi katerega je sredstvo pridobil.
//
// Posledici, ki sta del zasnove:
// 1. napake v opisu ni mogoce popraviti; popravek pomeni novo sredstvo,
// 2. vsebina zivi na IPFS in je dosegljiva, dokler je kdo pinja — CID na
// verigi doloca, KATERA vsebina je veljavna, ne zagotavlja pa hrambe.
// ── Cenitev sredstva: spremeni jo lahko SAMO UORS ──────────────────────────
//
// `assetValueUSD` je izjava o vrednosti realnega sredstva. Za tako izjavo
// odgovarja overitelj, ne skrbnik sistema; skrbnik lahko dejanje prepreci
// (`pause`, odvzem pooblastila), ne more pa ga opraviti namesto njega.
//
// Cenitev doloca tudi ceno, po kateri je sredstvo mogoce prvic prodati, zato
// bi pravica skrbnika pomenila, da skrbnik doloca prodajno ceno tujega
// sredstva. Sprememba gre skozi napoved in zamik, torej je javna vnaprej.
//
// ⚠️ Obe funkciji morata imeti ISTO omejitev. Ce bi eno napovedoval skrbnik
// in drugo izvajal overitelj, bi bila polovica postopka v napacnih rokah.
function napoviUpdateAssetValue(uint256 newValueUSD) external samoOveritelj {
_napovej(keccak256(abi.encode("updateAssetValue", newValueUSD)), "RWAToken.updateAssetValue");
}
function updateAssetValue(uint256 newValueUSD) external samoOveritelj {
_porabi(keccak256(abi.encode("updateAssetValue", newValueUSD)), "RWAToken.updateAssetValue");
assetValueUSD = newValueUSD;
emit AssetValueUpdated(newValueUSD);
}
/// @notice Onemogoceno: renounceOwnership() bi trajno ubil setKyc in
/// setFeeRecipient.
function renounceOwnership() public pure override {
revert("Renounce onemogocen");
}
}
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":"address","name":"_zkVerifier","internalType":"address"},{"type":"address","name":"_entropyOracle","internalType":"address"},{"type":"address","name":"_feeRecipient","internalType":"address"},{"type":"address","name":"_kyc","internalType":"address"},{"type":"address","name":"_lastnik","internalType":"address"},{"type":"address","name":"_uors","internalType":"address"}]},{"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":"NastavitveSpremenjene","inputs":[{"type":"address","name":"feeRecipient","internalType":"address","indexed":false},{"type":"address","name":"kyc","internalType":"address","indexed":false}],"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":"SredstvoUstvarjeno","inputs":[{"type":"address","name":"zeton","internalType":"address","indexed":true},{"type":"string","name":"ime","internalType":"string","indexed":false},{"type":"string","name":"simbol","internalType":"string","indexed":false},{"type":"uint256","name":"vrednostUSD","internalType":"uint256","indexed":false},{"type":"string","name":"metapodatkiCID","internalType":"string","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"entropyOracle","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeRecipient","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"jeNase","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"kyc","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"nastavi","inputs":[{"type":"address","name":"_feeRecipient","internalType":"address"},{"type":"address","name":"_kyc","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"sredstva","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"steviloSredstev","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"uors","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"zeton","internalType":"address"}],"name":"ustvariSredstvo","inputs":[{"type":"string","name":"ime","internalType":"string"},{"type":"string","name":"simbol","internalType":"string"},{"type":"string","name":"metapodatkiCID","internalType":"string"},{"type":"uint256","name":"vrednostUSD","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"vsaSredstva","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"zkVerifier","inputs":[]}]
Contract Creation Code
0x60e06040523480156200001157600080fd5b5060405162003ba938038062003ba9833981016040819052620000349162000275565b816001600160a01b0381166200006557604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000708162000208565b506001600160a01b038616620000c95760405162461bcd60e51b815260206004820152601360248201527f5a4b5665726966696572206a65206e756a656e0000000000000000000000000060448201526064016200005c565b6001600160a01b038416620001215760405162461bcd60e51b815260206004820152601560248201527f666565526563697069656e74206a65206e756a656e000000000000000000000060448201526064016200005c565b6001600160a01b0382166200016c5760405162461bcd60e51b815260206004820152601060248201526f2630b9ba3734b590353290373ab532b760811b60448201526064016200005c565b6001600160a01b038116620001c45760405162461bcd60e51b815260206004820152601560248201527f554f52535265676973747279206a65206e756a656e000000000000000000000060448201526064016200005c565b6001600160a01b0390811660c0529485166080525091831660a052600180549184166001600160a01b031992831617905560028054929093169116179055620002f6565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200027057600080fd5b919050565b60008060008060008060c087890312156200028f57600080fd5b6200029a8762000258565b9550620002aa6020880162000258565b9450620002ba6040880162000258565b9350620002ca6060880162000258565b9250620002da6080880162000258565b9150620002ea60a0880162000258565b90509295509295509295565b60805160a05160c05161386062000349600039600081816101640152818161044d015261072501526000818161010801526106c701526000818161024b0152818161069f015261080401526138606000f3fe60806040523480156200001157600080fd5b5060043610620000fd5760003560e01c8063880978dd1162000097578063a7a70b4f116200006e578063a7a70b4f146200020e578063d6df096d1462000245578063ee1f501b146200026d578063f2fde38b146200028457600080fd5b8063880978dd14620001d65780638da5cb5b14620001e857806390d6b45f14620001fa57600080fd5b80633f1b112f11620000d85780633f1b112f146200018657806346904840146200019f5780635c06ae1414620001b3578063715018a614620001cc57600080fd5b80630e78931d146200010257806314ae8689146200014757806329c3fe7c146200015e575b600080fd5b6200012a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6200012a6200015836600462000991565b6200029b565b6200012a7f000000000000000000000000000000000000000000000000000000000000000081565b62000190620002c6565b6040516200013e9190620009ab565b6001546200012a906001600160a01b031681565b620001ca620001c436600462000a17565b6200032a565b005b620001ca620003f6565b6003546040519081526020016200013e565b6000546001600160a01b03166200012a565b6002546200012a906001600160a01b031681565b620002346200021f36600462000a4f565b60046020526000908152604090205460ff1681565b60405190151581526020016200013e565b6200012a7f000000000000000000000000000000000000000000000000000000000000000081565b6200012a6200027e36600462000ac0565b62000435565b620001ca6200029536600462000a4f565b620008be565b60038181548110620002ac57600080fd5b6000918252602090912001546001600160a01b0316905081565b606060038054806020026020016040519081016040528092919081815260200182805480156200032057602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162000301575b5050505050905090565b6200033462000902565b6001600160a01b038216620003885760405162461bcd60e51b81526020600482015260156024820152743332b2a932b1b4b834b2b73a10353290373ab532b760591b60448201526064015b60405180910390fd5b600180546001600160a01b038481166001600160a01b03199283168117909355600280549185169190921681179091556040805192835260208301919091527fa57aa9b3e4cb6b9c016c34aab0f3df378c31c283f14ae35bd84dd656c58830e7910160405180910390a15050565b60405162461bcd60e51b81526020600482015260136024820152722932b737bab731b29037b732b6b7b3b7b1b2b760691b60448201526064016200037f565b6040516338260bcb60e11b81523360048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa1580156200049d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c3919062000b6d565b620005065760405162461bcd60e51b815260206004820152601260248201527129b0b6b7902aa7a9299037b832b930ba32b960711b60448201526064016200037f565b6000879003620005485760405162461bcd60e51b815260206004820152600c60248201526b496d65206a65206e756a6e6f60a01b60448201526064016200037f565b60008590036200058d5760405162461bcd60e51b815260206004820152600f60248201526e29b4b6b137b610353290373ab532b760891b60448201526064016200037f565b81600003620005d35760405162461bcd60e51b8152602060048201526011602482015270567265646e6f7374206a65206e756a6e6160781b60448201526064016200037f565b60405180610160016040528089898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f8a0181900481028201810190925288815291810191908990899081908401838280828437600092019190915250505090825250604080516020601f880181900481028201810190925286815291810191908790879081908401838280828437600092019190915250505090825250602081018490526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660408301527f000000000000000000000000000000000000000000000000000000000000000081166060830152600154811660808301526002541660a082015260c001620007166000546001600160a01b031690565b6001600160a01b0390811682527f000000000000000000000000000000000000000000000000000000000000000016602082015233604091820152516200075d9062000983565b62000769919062000bd9565b604051809103906000f08015801562000786573d6000803e3d6000fd5b506003805460018082019092557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b0319166001600160a01b03848116918217909255600081815260046020819052604091829020805460ff1916909517909455516319ee63c160e01b8152928301529192507f0000000000000000000000000000000000000000000000000000000000000000909116906319ee63c190602401600060405180830381600087803b1580156200084b57600080fd5b505af115801562000860573d6000803e3d6000fd5b50505050806001600160a01b03167fc62bc666583275a3880662ff8c669b31653375d9bbe9ff0e54a90eded8bbcbdd89898989878a8a604051620008ab979695949392919062000d26565b60405180910390a2979650505050505050565b620008c862000902565b6001600160a01b038116620008f457604051631e4fbdf760e01b8152600060048201526024016200037f565b620008ff8162000933565b50565b6000546001600160a01b03163314620009315760405163118cdaa760e01b81523360048201526024016200037f565b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612aae8062000d7d83390190565b600060208284031215620009a457600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015620009ee5783516001600160a01b031683529284019291840191600101620009c7565b50909695505050505050565b80356001600160a01b038116811462000a1257600080fd5b919050565b6000806040838503121562000a2b57600080fd5b62000a3683620009fa565b915062000a4660208401620009fa565b90509250929050565b60006020828403121562000a6257600080fd5b62000a6d82620009fa565b9392505050565b60008083601f84011262000a8757600080fd5b50813567ffffffffffffffff81111562000aa057600080fd5b60208301915083602082850101111562000ab957600080fd5b9250929050565b60008060008060008060006080888a03121562000adc57600080fd5b873567ffffffffffffffff8082111562000af557600080fd5b62000b038b838c0162000a74565b909950975060208a013591508082111562000b1d57600080fd5b62000b2b8b838c0162000a74565b909750955060408a013591508082111562000b4557600080fd5b5062000b548a828b0162000a74565b989b979a50959894979596606090950135949350505050565b60006020828403121562000b8057600080fd5b8151801515811462000a6d57600080fd5b6000815180845260005b8181101562000bb95760208185018101518683018201520162000b9b565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000825161016080602085015262000bfa61018085018362000b91565b91506020850151601f198086850301604087015262000c1a848362000b91565b935060408701519150808685030160608701525062000c3a838262000b91565b92505060608501516080850152608085015162000c6260a08601826001600160a01b03169052565b5060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e085015161010062000caa818701836001600160a01b03169052565b860151905061012062000cc7868201836001600160a01b03169052565b860151905061014062000ce4868201836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600062000d3c60808301898b62000cfd565b828103602084015262000d5181888a62000cfd565b9050856040840152828103606084015262000d6e81858762000cfd565b9a995050505050505050505056fe60e06040523480156200001157600080fd5b5060405162002aae38038062002aae8339810160408190526200003491620003eb565b6101008101518151602083015160036200004f8382620005d9565b5060046200005e8282620005d9565b5050506001600160a01b0381166200009157604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6200009c8162000256565b5060808101516001600160a01b0316620000f95760405162461bcd60e51b815260206004820152601360248201527f5a4b5665726966696572206a65206e756a656e00000000000000000000000000604482015260640162000088565b60c08101516001600160a01b0316620001555760405162461bcd60e51b815260206004820152601560248201527f666565526563697069656e74206a65206e756a656e0000000000000000000000604482015260640162000088565b6101008101516001600160a01b0316620001a55760405162461bcd60e51b815260206004820152601060248201526f2630b9ba3734b590353290373ab532b760811b604482015260640162000088565b6040810151600790620001b99082620005d9565b506060810151600855608080820151600980546001600160a01b03199081166001600160a01b039384161790915560a0840151600a8054831691841691909117905560c080850151600b8054841691851691909117905560e0850151600d8054909316908416179091556101208401518216905261014083015116905262000240620002a8565b6200024c9042620006a5565b60a05250620006cd565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006101714614620002bd57610258620002c2565b6202a3005b62ffffff16905090565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b0381118282101715620003085762000308620002cc565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620003395762000339620002cc565b604052919050565b600082601f8301126200035357600080fd5b81516001600160401b038111156200036f576200036f620002cc565b602062000385601f8301601f191682016200030e565b82815285828487010111156200039a57600080fd5b60005b83811015620003ba5785810183015182820184015282016200039d565b506000928101909101919091529392505050565b80516001600160a01b0381168114620003e657600080fd5b919050565b600060208284031215620003fe57600080fd5b81516001600160401b03808211156200041657600080fd5b9083019061016082860312156200042c57600080fd5b62000436620002e2565b8251828111156200044657600080fd5b620004548782860162000341565b8252506020830151828111156200046a57600080fd5b620004788782860162000341565b6020830152506040830151828111156200049157600080fd5b6200049f8782860162000341565b60408301525060608301516060820152620004bd60808401620003ce565b6080820152620004d060a08401620003ce565b60a0820152620004e360c08401620003ce565b60c0820152620004f660e08401620003ce565b60e082015261010091506200050d828401620003ce565b82820152610120915062000523828401620003ce565b82820152610140915062000539828401620003ce565b91810191909152949350505050565b600181811c908216806200055d57607f821691505b6020821081036200057e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005d4576000816000526020600020601f850160051c81016020861015620005af5750805b601f850160051c820191505b81811015620005d057828155600101620005bb565b5050505b505050565b81516001600160401b03811115620005f557620005f5620002cc565b6200060d8162000606845462000548565b8462000584565b602080601f8311600181146200064557600084156200062c5750858301515b600019600386901b1c1916600185901b178555620005d0565b600085815260208120601f198616915b82811015620006765788860151825594840194600190910190840162000655565b5085821015620006955787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115620006c757634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c051612348620007666000396000818161037c015281816106aa015281816106f001528181610a4901528181610a8f015281816111590152818161119f0152818161148801526114ce0152600081816105f401528181610828015281816108670152611c950152600081816103c60152818161098b015281816109da015281816113ca015261141901526123486000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c8063776528cd11610146578063c1da7c97116100c3578063dd62ed3e11610087578063dd62ed3e14610573578063e74b981b146105ac578063e826f69a146105bf578063f2fde38b146105c9578063f7dc9243146105dc578063f9728ca1146105ef57600080fd5b8063c1da7c9714610524578063c30a0f251461052c578063cde2202a1461054f578063d48693d114610558578063d6df096d1461056057600080fd5b806399c272061161010a57806399c27206146104db578063a5826652146104ee578063a9059cbb146104f6578063b007d5fc14610509578063bfba6d5d1461051157600080fd5b8063776528cd146104655780638cc9d1071461049c5780638da5cb5b146104af57806390d6b45f146104c057806395d89b41146104d357600080fd5b8063263c1e61116101df57806346904840116101a357806346904840146103e85780635c57d8a8146103fb5780636a3b5c4d1461040e57806370a0823114610421578063715018a61461044a57806376e382c81461045257600080fd5b8063263c1e611461036457806329c3fe7c146103775780632bcc0bbe1461039e578063313ce567146103b2578063418ee99d146103c157600080fd5b8063179f548a11610226578063179f548a1461030757806318160ddd1461030f57806323b872dd1461031757806323eca6651461032a57806325b49a501461035157600080fd5b806306fdde031461026357806307601d27146102815780630854eef51461028b578063095ea7b3146102b95780630e78931d146102dc575b600080fd5b61026b610616565b6040516102789190611f67565b60405180910390f35b6102896106a8565b005b6102ab610299366004611f81565b60066020526000908152604090205481565b604051908152602001610278565b6102cc6102c7366004611fb6565b6107e3565b6040519015158152602001610278565b600a546102ef906001600160a01b031681565b6040516001600160a01b039091168152602001610278565b6102ab603281565b6002546102ab565b6102cc610325366004611fe0565b6107fd565b610332610821565b6040805193151584526020840192909252151590820152606001610278565b61028961035f36600461201c565b610899565b61028961037236600461201c565b61092a565b6102ef7f000000000000000000000000000000000000000000000000000000000000000081565b600d546102cc90600160a01b900460ff1681565b60405160128152602001610278565b6102ef7f000000000000000000000000000000000000000000000000000000000000000081565b600b546102ef906001600160a01b031681565b610289610409366004611f81565b610989565b61028961041c366004612037565b610c0e565b6102ab61042f36600461201c565b6001600160a01b031660009081526020819052604090205490565b610289610dc2565b61028961046036600461206a565b610e00565b610478610473366004611f81565b610ea7565b60408051941515855260208501939093529183015215156060820152608001610278565b6102896104aa366004611fb6565b610f14565b6005546001600160a01b03166102ef565b600d546102ef906001600160a01b031681565b61026b610ff4565b6102896104e936600461201c565b611003565b61026b6110ac565b6102cc610504366004611fb6565b61113a565b6102ab611148565b600c546102ef906001600160a01b031681565b610289611157565b6102cc61053a366004611f81565b600e6020526000908152604090205460ff1681565b6102ab60085481565b6102ab611293565b6009546102ef906001600160a01b031681565b6102ab6105813660046120e6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102896105ba36600461201c565b6112b5565b6102ab62093a8081565b6102896105d736600461201c565b61138d565b6102896105ea366004611f81565b6113c8565b6102ab7f000000000000000000000000000000000000000000000000000000000000000081565b60606003805461062590612119565b80601f016020809104026020016040519081016040528092919081815260200182805461065190612119565b801561069e5780601f106106735761010080835404028352916020019161069e565b820191906000526020600020905b81548152906001019060200180831161068157829003601f168201915b5050505050905090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161580159061076357506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa15801561073f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107639190612153565b6107a95760405162461bcd60e51b815260206004820152601260248201527129b0b6b7902aa7a9299037b832b930ba32b960711b60448201526064015b60405180910390fd5b600d805460ff60a01b1916905560405133907fae0ecc60019f8d35cb80c8e02e2aeb74213dfa85a8557ba667398dc103b0e77a90600090a2565b6000336107f1818585611612565b60019150505b92915050565b60003361080b858285611624565b6108168585856116a3565b506001949350505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000042101580156108605750600d54600160a01b900460ff16155b600d5490947f00000000000000000000000000000000000000000000000000000000000000009450600160a01b90910460ff1692509050565b6108a1611702565b6001600160a01b0381166108c75760405162461bcd60e51b81526004016107a090612175565b610927816040516020016108db919061219b565b60405160208183030381529060405280519060200120604051806040016040528060188152602001771495d0551bdad95b8b9cd95d119959549958da5c1a595b9d60421b815250611731565b50565b610932611702565b6109278160405160200161094691906121d5565b604051602081830303815290604052805190602001206040518060400160405280600f81526020016e525741546f6b656e2e7365744b796360881b815250611731565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166109cf5760405162461bcd60e51b81526004016107a090612206565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a475760405162461bcd60e51b815260206004820152601c60248201527f53616d6f206f7665726974656c6a20746567612073726564737476610000000060448201526064016107a0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615801590610b0257506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa158015610ade573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b029190612153565b610b4e5760405162461bcd60e51b815260206004820152601b60248201527f4f7665726974656c6a206e692076656320706f6f626c617363656e000000000060448201526064016107a0565b6040805160208101829052601060608201526f757064617465417373657456616c756560801b6080820152908101829052610bd39060a0016040516020818303038152906040528051906020012060405180604001604052806019815260200178525741546f6b656e2e757064617465417373657456616c756560381b8152506117e4565b60088190556040518181527f1cb5e221120a70c5978375b275179418e0cc46d0390597fad5b2d8757fe9eab59060200160405180910390a150565b6009546001600160a01b03163314610c5b5760405162461bcd60e51b815260206004820152601060248201526f27b7363c902d25903b32b934b334b2b960811b60448201526064016107a0565b6000818152600e602052604090205460ff1615610caf5760405162461bcd60e51b8152602060048201526012602482015271141c9bdbd988185b1c9958591e481d5cd95960721b60448201526064016107a0565b600c546001600160a01b031615610d015760405162461bcd60e51b8152602060048201526016602482015275537265647374766f206a65207a6520736b6f76616e6f60501b60448201526064016107a0565b6000818152600e60205260409020805460ff19166001179055600c80546001600160a81b0319166001600160a01b03851617600160a01b179055610d45838361190d565b60408051838152602081018390526001600160a01b038516917f7369d801113c713520ca653010d32c6bcd6778f0ffb3df0bc9efb8d85b687e44910160405180910390a26040516001600160a01b038416907fe2cdd6bfbb0efc5299e0840dd4af6d4c9a195224ebad256485e9990726fd041c90600090a2505050565b60405162461bcd60e51b81526020600482015260136024820152722932b737bab731b29037b732b6b7b3b7b1b2b760691b60448201526064016107a0565b610e08611702565b6000838152600660205260408120549003610e555760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b60448201526064016107a0565b600083815260066020526040808220919091555183907f72003eda7c2c39777210bccbf69141a92bbe56d746914a16f5ee3aaf5e6f7a8390610e9a9085908590612249565b60405180910390a2505050565b600081815260066020526040812054819081908190808203610ed757600080600080945094509450945050610f0d565b600181610ee762093a808261228e565b834210158015610f035750610eff62093a808561228e565b4211155b9450945094509450505b9193509193565b6009546001600160a01b03163314610f615760405162461bcd60e51b815260206004820152601060248201526f27b7363c902d25903b32b934b334b2b960811b60448201526064016107a0565b6001600160a01b038216610f875760405162461bcd60e51b81526004016107a090612175565b600c54600160a01b900460ff16610fd95760405162461bcd60e51b815260206004820152601660248201527550726f76697a696a61206272657a206b6f76616e6a6160501b60448201526064016107a0565b600c805460ff60a01b19169055610ff0828261190d565b5050565b60606004805461062590612119565b61100b611702565b6110628160405160200161101f91906121d5565b604051602081830303815290604052805190602001206040518060400160405280600f81526020016e525741546f6b656e2e7365744b796360881b8152506117e4565b600d80546001600160a01b0319166001600160a01b0383169081179091556040517f9f5f8fd48aa64bb8a94c00d6adfc92b215610db623c189eb30698be4581265a490600090a250565b600780546110b990612119565b80601f01602080910402602001604051908101604052809291908181526020018280546110e590612119565b80156111325780601f1061110757610100808354040283529160200191611132565b820191906000526020600020905b81548152906001019060200180831161111557829003601f168201915b505050505081565b6000336107f18185856116a3565b6000611152611293565b905090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161580159061121257506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa1580156111ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112129190612153565b6112535760405162461bcd60e51b815260206004820152601260248201527129b0b6b7902aa7a9299037b832b930ba32b960711b60448201526064016107a0565b600d805460ff60a01b1916600160a01b17905560405133907f481d73db1c84a4cd0734a718818b266e3b59f2e485d8ba806e15763777d9d00690600090a2565b600061017146146112a6576102586112ab565b6202a3005b62ffffff16905090565b6112bd611702565b6001600160a01b0381166112e35760405162461bcd60e51b81526004016107a090612175565b611343816040516020016112f7919061219b565b60405160208183030381529060405280519060200120604051806040016040528060188152602001771495d0551bdad95b8b9cd95d119959549958da5c1a595b9d60421b8152506117e4565b600b80546001600160a01b0319166001600160a01b0383169081179091556040517f7a7b5a0a132f9e0581eb8527f66eae9ee89c2a3e79d4ac7e41a1f1f4d48a7fc290600090a250565b611395611702565b6001600160a01b0381166113bf57604051631e4fbdf760e01b8152600060048201526024016107a0565b61092781611943565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661140e5760405162461bcd60e51b81526004016107a090612206565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146114865760405162461bcd60e51b815260206004820152601c60248201527f53616d6f206f7665726974656c6a20746567612073726564737476610000000060448201526064016107a0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161580159061154157506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa15801561151d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115419190612153565b61158d5760405162461bcd60e51b815260206004820152601b60248201527f4f7665726974656c6a206e692076656320706f6f626c617363656e000000000060448201526064016107a0565b6040805160208101829052601060608201526f757064617465417373657456616c756560801b60808201529081018290526109279060a0016040516020818303038152906040528051906020012060405180604001604052806019815260200178525741546f6b656e2e757064617465417373657456616c756560381b815250611731565b61161f8383836001611995565b505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981101561169d578181101561168e57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016107a0565b61169d84848484036000611995565b50505050565b6001600160a01b0383166116cd57604051634b637e8f60e11b8152600060048201526024016107a0565b6001600160a01b0382166116f75760405163ec442f0560e01b8152600060048201526024016107a0565b61161f838383611a6a565b6005546001600160a01b0316331461172f5760405163118cdaa760e01b81523360048201526024016107a0565b565b6000828152600660205260409020541561177d5760405162461bcd60e51b815260206004820152600d60248201526c5a65206e61706f766564616e6f60981b60448201526064016107a0565b6000611787611293565b611791904261228e565b60008481526006602052604090208190559050827f63a0d065f46e07e30a4f246d28eb53f839982100439173db92dbd5700ab37c1583836117d562093a808261228e565b604051610e9a939291906122a1565b600082815260066020526040812054908190036118335760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b60448201526064016107a0565b804210156118795760405162461bcd60e51b815260206004820152601360248201527216985b5a5ac81cd9481b9a481c1bdd195ad95b606a1b60448201526064016107a0565b61188662093a808261228e565b4211156118ca5760405162461bcd60e51b81526020600482015260126024820152714e61706f766564206a6520706f74656b6c6160701b60448201526064016107a0565b600083815260066020526040808220919091555183907ffac4537038ebc9eaa00d86a88a6c2e268012d306f6442966aab36014a195432390610e9a908590611f67565b6001600160a01b0382166119375760405163ec442f0560e01b8152600060048201526024016107a0565b610ff060008383611a6a565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0384166119bf5760405163e602df0560e01b8152600060048201526024016107a0565b6001600160a01b0383166119e957604051634a1406b160e11b8152600060048201526024016107a0565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561169d57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611a5c91815260200190565b60405180910390a350505050565b600d546001600160a01b03848116159184821615911615611c3b5780158015611aa15750600b546001600160a01b03858116911614155b15611b6057600d54604051633af32abf60e01b81526001600160a01b03868116600483015290911690633af32abf90602401602060405180830381865afa158015611af0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b149190612153565b611b605760405162461bcd60e51b815260206004820152601a60248201527f5072656a656d6e696b206e69204b5943207072657665726a656e00000000000060448201526064016107a0565b81158015611b7c5750600b546001600160a01b03868116911614155b15611c3b57600d54604051633af32abf60e01b81526001600160a01b03878116600483015290911690633af32abf90602401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef9190612153565b611c3b5760405162461bcd60e51b815260206004820152601c60248201527f506f73696c6a6174656c6a206e69204b5943207072657665726a656e0000000060448201526064016107a0565b81611d0357600d54600160a01b900460ff1615611c935760405162461bcd60e51b8152602060048201526016602482015275537265647374766f206a65207a616d727a6e6a656e6f60501b60448201526064016107a0565b7f0000000000000000000000000000000000000000000000000000000000000000421015611d035760405162461bcd60e51b815260206004820181905260248201527f537265647374766f207365206e6920616b7469766e6f207a61207072656e6f7360448201526064016107a0565b8180611d0c5750805b80611d245750600b546001600160a01b038681169116145b80611d3c5750600b546001600160a01b038581169116145b15611d5357611d4c858585611df7565b5050505050565b6000612710611d636032866122c6565b611d6d91906122dd565b90506000611d7b82866122ff565b600b54909150611d969088906001600160a01b031684611df7565b611da1878783611df7565b856001600160a01b0316876001600160a01b03167ff403ce23f2694cf9716913477865dd71892b2d8917c097372a485281654fdcb184604051611de691815260200190565b60405180910390a350505050505050565b6001600160a01b038316611e22578060026000828254611e17919061228e565b90915550611e949050565b6001600160a01b03831660009081526020819052604090205481811015611e755760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016107a0565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b038216611eb057600280548290039055611ecf565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611f1491815260200190565b60405180910390a3505050565b6000815180845260005b81811015611f4757602081850181015186830182015201611f2b565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000611f7a6020830184611f21565b9392505050565b600060208284031215611f9357600080fd5b5035919050565b80356001600160a01b0381168114611fb157600080fd5b919050565b60008060408385031215611fc957600080fd5b611fd283611f9a565b946020939093013593505050565b600080600060608486031215611ff557600080fd5b611ffe84611f9a565b925061200c60208501611f9a565b9150604084013590509250925092565b60006020828403121561202e57600080fd5b611f7a82611f9a565b60008060006060848603121561204c57600080fd5b61205584611f9a565b95602085013595506040909401359392505050565b60008060006040848603121561207f57600080fd5b83359250602084013567ffffffffffffffff8082111561209e57600080fd5b818601915086601f8301126120b257600080fd5b8135818111156120c157600080fd5b8760208285010111156120d357600080fd5b6020830194508093505050509250925092565b600080604083850312156120f957600080fd5b61210283611f9a565b915061211060208401611f9a565b90509250929050565b600181811c9082168061212d57607f821691505b60208210810361214d57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561216557600080fd5b81518015158114611f7a57600080fd5b6020808252600c908201526b5a65726f206164647265737360a01b604082015260600190565b6040808252600f908201526e1cd95d119959549958da5c1a595b9d608a1b60608201526001600160a01b0391909116602082015260800190565b6040808252600690820152657365744b796360d01b60608201526001600160a01b0391909116602082015260800190565b60208082526023908201527f537265647374766f206e696d61207a61706973616e656761206f7665726974656040820152626c6a6160e81b606082015260800190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107f7576107f7612278565b6060815260006122b46060830186611f21565b60208301949094525060400152919050565b80820281158282048414176107f7576107f7612278565b6000826122fa57634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156107f7576107f761227856fea264697066735822122034deffb9c10289851c0ded01f317c164e72f10dd6afd348e6ab4769b1ee46a6464736f6c63430008180033a2646970667358221220ce7d6c0af0775c0acfd348ad83e9c16517fcb7eb57396990dd6fb705844d439864736f6c63430008180033000000000000000000000000cf59b47b780a73ee10aeea21a81dfc3cb70b9c88000000000000000000000000f119beb1b343e46c4ed0e78362cd3f87e87ef4cc00000000000000000000000050555531d7a9ae79a5ad9100f114def88c6691d9000000000000000000000000d37d29526d271770f42c2553faae7f282effc1630000000000000000000000005a5db3d01a38d640a81182b1769a9f1e4d1f0f7400000000000000000000000016eeba545a07a88cdf21cfdde973ee67cdc32000
Deployed ByteCode
0x60806040523480156200001157600080fd5b5060043610620000fd5760003560e01c8063880978dd1162000097578063a7a70b4f116200006e578063a7a70b4f146200020e578063d6df096d1462000245578063ee1f501b146200026d578063f2fde38b146200028457600080fd5b8063880978dd14620001d65780638da5cb5b14620001e857806390d6b45f14620001fa57600080fd5b80633f1b112f11620000d85780633f1b112f146200018657806346904840146200019f5780635c06ae1414620001b3578063715018a614620001cc57600080fd5b80630e78931d146200010257806314ae8689146200014757806329c3fe7c146200015e575b600080fd5b6200012a7f000000000000000000000000f119beb1b343e46c4ed0e78362cd3f87e87ef4cc81565b6040516001600160a01b0390911681526020015b60405180910390f35b6200012a6200015836600462000991565b6200029b565b6200012a7f00000000000000000000000016eeba545a07a88cdf21cfdde973ee67cdc3200081565b62000190620002c6565b6040516200013e9190620009ab565b6001546200012a906001600160a01b031681565b620001ca620001c436600462000a17565b6200032a565b005b620001ca620003f6565b6003546040519081526020016200013e565b6000546001600160a01b03166200012a565b6002546200012a906001600160a01b031681565b620002346200021f36600462000a4f565b60046020526000908152604090205460ff1681565b60405190151581526020016200013e565b6200012a7f000000000000000000000000cf59b47b780a73ee10aeea21a81dfc3cb70b9c8881565b6200012a6200027e36600462000ac0565b62000435565b620001ca6200029536600462000a4f565b620008be565b60038181548110620002ac57600080fd5b6000918252602090912001546001600160a01b0316905081565b606060038054806020026020016040519081016040528092919081815260200182805480156200032057602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831162000301575b5050505050905090565b6200033462000902565b6001600160a01b038216620003885760405162461bcd60e51b81526020600482015260156024820152743332b2a932b1b4b834b2b73a10353290373ab532b760591b60448201526064015b60405180910390fd5b600180546001600160a01b038481166001600160a01b03199283168117909355600280549185169190921681179091556040805192835260208301919091527fa57aa9b3e4cb6b9c016c34aab0f3df378c31c283f14ae35bd84dd656c58830e7910160405180910390a15050565b60405162461bcd60e51b81526020600482015260136024820152722932b737bab731b29037b732b6b7b3b7b1b2b760691b60448201526064016200037f565b6040516338260bcb60e11b81523360048201526000907f00000000000000000000000016eeba545a07a88cdf21cfdde973ee67cdc320006001600160a01b03169063704c179690602401602060405180830381865afa1580156200049d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c3919062000b6d565b620005065760405162461bcd60e51b815260206004820152601260248201527129b0b6b7902aa7a9299037b832b930ba32b960711b60448201526064016200037f565b6000879003620005485760405162461bcd60e51b815260206004820152600c60248201526b496d65206a65206e756a6e6f60a01b60448201526064016200037f565b60008590036200058d5760405162461bcd60e51b815260206004820152600f60248201526e29b4b6b137b610353290373ab532b760891b60448201526064016200037f565b81600003620005d35760405162461bcd60e51b8152602060048201526011602482015270567265646e6f7374206a65206e756a6e6160781b60448201526064016200037f565b60405180610160016040528089898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250604080516020601f8a0181900481028201810190925288815291810191908990899081908401838280828437600092019190915250505090825250604080516020601f880181900481028201810190925286815291810191908790879081908401838280828437600092019190915250505090825250602081018490526001600160a01b037f000000000000000000000000cf59b47b780a73ee10aeea21a81dfc3cb70b9c88811660408301527f000000000000000000000000f119beb1b343e46c4ed0e78362cd3f87e87ef4cc81166060830152600154811660808301526002541660a082015260c001620007166000546001600160a01b031690565b6001600160a01b0390811682527f00000000000000000000000016eeba545a07a88cdf21cfdde973ee67cdc3200016602082015233604091820152516200075d9062000983565b62000769919062000bd9565b604051809103906000f08015801562000786573d6000803e3d6000fd5b506003805460018082019092557fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0180546001600160a01b0319166001600160a01b03848116918217909255600081815260046020819052604091829020805460ff1916909517909455516319ee63c160e01b8152928301529192507f000000000000000000000000cf59b47b780a73ee10aeea21a81dfc3cb70b9c88909116906319ee63c190602401600060405180830381600087803b1580156200084b57600080fd5b505af115801562000860573d6000803e3d6000fd5b50505050806001600160a01b03167fc62bc666583275a3880662ff8c669b31653375d9bbe9ff0e54a90eded8bbcbdd89898989878a8a604051620008ab979695949392919062000d26565b60405180910390a2979650505050505050565b620008c862000902565b6001600160a01b038116620008f457604051631e4fbdf760e01b8152600060048201526024016200037f565b620008ff8162000933565b50565b6000546001600160a01b03163314620009315760405163118cdaa760e01b81523360048201526024016200037f565b565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612aae8062000d7d83390190565b600060208284031215620009a457600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015620009ee5783516001600160a01b031683529284019291840191600101620009c7565b50909695505050505050565b80356001600160a01b038116811462000a1257600080fd5b919050565b6000806040838503121562000a2b57600080fd5b62000a3683620009fa565b915062000a4660208401620009fa565b90509250929050565b60006020828403121562000a6257600080fd5b62000a6d82620009fa565b9392505050565b60008083601f84011262000a8757600080fd5b50813567ffffffffffffffff81111562000aa057600080fd5b60208301915083602082850101111562000ab957600080fd5b9250929050565b60008060008060008060006080888a03121562000adc57600080fd5b873567ffffffffffffffff8082111562000af557600080fd5b62000b038b838c0162000a74565b909950975060208a013591508082111562000b1d57600080fd5b62000b2b8b838c0162000a74565b909750955060408a013591508082111562000b4557600080fd5b5062000b548a828b0162000a74565b989b979a50959894979596606090950135949350505050565b60006020828403121562000b8057600080fd5b8151801515811462000a6d57600080fd5b6000815180845260005b8181101562000bb95760208185018101518683018201520162000b9b565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000825161016080602085015262000bfa61018085018362000b91565b91506020850151601f198086850301604087015262000c1a848362000b91565b935060408701519150808685030160608701525062000c3a838262000b91565b92505060608501516080850152608085015162000c6260a08601826001600160a01b03169052565b5060a08501516001600160a01b03811660c08601525060c08501516001600160a01b03811660e08601525060e085015161010062000caa818701836001600160a01b03169052565b860151905061012062000cc7868201836001600160a01b03169052565b860151905061014062000ce4868201836001600160a01b03169052565b909501516001600160a01b031693019290925250919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600062000d3c60808301898b62000cfd565b828103602084015262000d5181888a62000cfd565b9050856040840152828103606084015262000d6e81858762000cfd565b9a995050505050505050505056fe60e06040523480156200001157600080fd5b5060405162002aae38038062002aae8339810160408190526200003491620003eb565b6101008101518151602083015160036200004f8382620005d9565b5060046200005e8282620005d9565b5050506001600160a01b0381166200009157604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6200009c8162000256565b5060808101516001600160a01b0316620000f95760405162461bcd60e51b815260206004820152601360248201527f5a4b5665726966696572206a65206e756a656e00000000000000000000000000604482015260640162000088565b60c08101516001600160a01b0316620001555760405162461bcd60e51b815260206004820152601560248201527f666565526563697069656e74206a65206e756a656e0000000000000000000000604482015260640162000088565b6101008101516001600160a01b0316620001a55760405162461bcd60e51b815260206004820152601060248201526f2630b9ba3734b590353290373ab532b760811b604482015260640162000088565b6040810151600790620001b99082620005d9565b506060810151600855608080820151600980546001600160a01b03199081166001600160a01b039384161790915560a0840151600a8054831691841691909117905560c080850151600b8054841691851691909117905560e0850151600d8054909316908416179091556101208401518216905261014083015116905262000240620002a8565b6200024c9042620006a5565b60a05250620006cd565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006101714614620002bd57610258620002c2565b6202a3005b62ffffff16905090565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b0381118282101715620003085762000308620002cc565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620003395762000339620002cc565b604052919050565b600082601f8301126200035357600080fd5b81516001600160401b038111156200036f576200036f620002cc565b602062000385601f8301601f191682016200030e565b82815285828487010111156200039a57600080fd5b60005b83811015620003ba5785810183015182820184015282016200039d565b506000928101909101919091529392505050565b80516001600160a01b0381168114620003e657600080fd5b919050565b600060208284031215620003fe57600080fd5b81516001600160401b03808211156200041657600080fd5b9083019061016082860312156200042c57600080fd5b62000436620002e2565b8251828111156200044657600080fd5b620004548782860162000341565b8252506020830151828111156200046a57600080fd5b620004788782860162000341565b6020830152506040830151828111156200049157600080fd5b6200049f8782860162000341565b60408301525060608301516060820152620004bd60808401620003ce565b6080820152620004d060a08401620003ce565b60a0820152620004e360c08401620003ce565b60c0820152620004f660e08401620003ce565b60e082015261010091506200050d828401620003ce565b82820152610120915062000523828401620003ce565b82820152610140915062000539828401620003ce565b91810191909152949350505050565b600181811c908216806200055d57607f821691505b6020821081036200057e57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620005d4576000816000526020600020601f850160051c81016020861015620005af5750805b601f850160051c820191505b81811015620005d057828155600101620005bb565b5050505b505050565b81516001600160401b03811115620005f557620005f5620002cc565b6200060d8162000606845462000548565b8462000584565b602080601f8311600181146200064557600084156200062c5750858301515b600019600386901b1c1916600185901b178555620005d0565b600085815260208120601f198616915b82811015620006765788860151825594840194600190910190840162000655565b5085821015620006955787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115620006c757634e487b7160e01b600052601160045260246000fd5b92915050565b60805160a05160c051612348620007666000396000818161037c015281816106aa015281816106f001528181610a4901528181610a8f015281816111590152818161119f0152818161148801526114ce0152600081816105f401528181610828015281816108670152611c950152600081816103c60152818161098b015281816109da015281816113ca015261141901526123486000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c8063776528cd11610146578063c1da7c97116100c3578063dd62ed3e11610087578063dd62ed3e14610573578063e74b981b146105ac578063e826f69a146105bf578063f2fde38b146105c9578063f7dc9243146105dc578063f9728ca1146105ef57600080fd5b8063c1da7c9714610524578063c30a0f251461052c578063cde2202a1461054f578063d48693d114610558578063d6df096d1461056057600080fd5b806399c272061161010a57806399c27206146104db578063a5826652146104ee578063a9059cbb146104f6578063b007d5fc14610509578063bfba6d5d1461051157600080fd5b8063776528cd146104655780638cc9d1071461049c5780638da5cb5b146104af57806390d6b45f146104c057806395d89b41146104d357600080fd5b8063263c1e61116101df57806346904840116101a357806346904840146103e85780635c57d8a8146103fb5780636a3b5c4d1461040e57806370a0823114610421578063715018a61461044a57806376e382c81461045257600080fd5b8063263c1e611461036457806329c3fe7c146103775780632bcc0bbe1461039e578063313ce567146103b2578063418ee99d146103c157600080fd5b8063179f548a11610226578063179f548a1461030757806318160ddd1461030f57806323b872dd1461031757806323eca6651461032a57806325b49a501461035157600080fd5b806306fdde031461026357806307601d27146102815780630854eef51461028b578063095ea7b3146102b95780630e78931d146102dc575b600080fd5b61026b610616565b6040516102789190611f67565b60405180910390f35b6102896106a8565b005b6102ab610299366004611f81565b60066020526000908152604090205481565b604051908152602001610278565b6102cc6102c7366004611fb6565b6107e3565b6040519015158152602001610278565b600a546102ef906001600160a01b031681565b6040516001600160a01b039091168152602001610278565b6102ab603281565b6002546102ab565b6102cc610325366004611fe0565b6107fd565b610332610821565b6040805193151584526020840192909252151590820152606001610278565b61028961035f36600461201c565b610899565b61028961037236600461201c565b61092a565b6102ef7f000000000000000000000000000000000000000000000000000000000000000081565b600d546102cc90600160a01b900460ff1681565b60405160128152602001610278565b6102ef7f000000000000000000000000000000000000000000000000000000000000000081565b600b546102ef906001600160a01b031681565b610289610409366004611f81565b610989565b61028961041c366004612037565b610c0e565b6102ab61042f36600461201c565b6001600160a01b031660009081526020819052604090205490565b610289610dc2565b61028961046036600461206a565b610e00565b610478610473366004611f81565b610ea7565b60408051941515855260208501939093529183015215156060820152608001610278565b6102896104aa366004611fb6565b610f14565b6005546001600160a01b03166102ef565b600d546102ef906001600160a01b031681565b61026b610ff4565b6102896104e936600461201c565b611003565b61026b6110ac565b6102cc610504366004611fb6565b61113a565b6102ab611148565b600c546102ef906001600160a01b031681565b610289611157565b6102cc61053a366004611f81565b600e6020526000908152604090205460ff1681565b6102ab60085481565b6102ab611293565b6009546102ef906001600160a01b031681565b6102ab6105813660046120e6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6102896105ba36600461201c565b6112b5565b6102ab62093a8081565b6102896105d736600461201c565b61138d565b6102896105ea366004611f81565b6113c8565b6102ab7f000000000000000000000000000000000000000000000000000000000000000081565b60606003805461062590612119565b80601f016020809104026020016040519081016040528092919081815260200182805461065190612119565b801561069e5780601f106106735761010080835404028352916020019161069e565b820191906000526020600020905b81548152906001019060200180831161068157829003601f168201915b5050505050905090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161580159061076357506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa15801561073f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107639190612153565b6107a95760405162461bcd60e51b815260206004820152601260248201527129b0b6b7902aa7a9299037b832b930ba32b960711b60448201526064015b60405180910390fd5b600d805460ff60a01b1916905560405133907fae0ecc60019f8d35cb80c8e02e2aeb74213dfa85a8557ba667398dc103b0e77a90600090a2565b6000336107f1818585611612565b60019150505b92915050565b60003361080b858285611624565b6108168585856116a3565b506001949350505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000042101580156108605750600d54600160a01b900460ff16155b600d5490947f00000000000000000000000000000000000000000000000000000000000000009450600160a01b90910460ff1692509050565b6108a1611702565b6001600160a01b0381166108c75760405162461bcd60e51b81526004016107a090612175565b610927816040516020016108db919061219b565b60405160208183030381529060405280519060200120604051806040016040528060188152602001771495d0551bdad95b8b9cd95d119959549958da5c1a595b9d60421b815250611731565b50565b610932611702565b6109278160405160200161094691906121d5565b604051602081830303815290604052805190602001206040518060400160405280600f81526020016e525741546f6b656e2e7365744b796360881b815250611731565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166109cf5760405162461bcd60e51b81526004016107a090612206565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a475760405162461bcd60e51b815260206004820152601c60248201527f53616d6f206f7665726974656c6a20746567612073726564737476610000000060448201526064016107a0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031615801590610b0257506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa158015610ade573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b029190612153565b610b4e5760405162461bcd60e51b815260206004820152601b60248201527f4f7665726974656c6a206e692076656320706f6f626c617363656e000000000060448201526064016107a0565b6040805160208101829052601060608201526f757064617465417373657456616c756560801b6080820152908101829052610bd39060a0016040516020818303038152906040528051906020012060405180604001604052806019815260200178525741546f6b656e2e757064617465417373657456616c756560381b8152506117e4565b60088190556040518181527f1cb5e221120a70c5978375b275179418e0cc46d0390597fad5b2d8757fe9eab59060200160405180910390a150565b6009546001600160a01b03163314610c5b5760405162461bcd60e51b815260206004820152601060248201526f27b7363c902d25903b32b934b334b2b960811b60448201526064016107a0565b6000818152600e602052604090205460ff1615610caf5760405162461bcd60e51b8152602060048201526012602482015271141c9bdbd988185b1c9958591e481d5cd95960721b60448201526064016107a0565b600c546001600160a01b031615610d015760405162461bcd60e51b8152602060048201526016602482015275537265647374766f206a65207a6520736b6f76616e6f60501b60448201526064016107a0565b6000818152600e60205260409020805460ff19166001179055600c80546001600160a81b0319166001600160a01b03851617600160a01b179055610d45838361190d565b60408051838152602081018390526001600160a01b038516917f7369d801113c713520ca653010d32c6bcd6778f0ffb3df0bc9efb8d85b687e44910160405180910390a26040516001600160a01b038416907fe2cdd6bfbb0efc5299e0840dd4af6d4c9a195224ebad256485e9990726fd041c90600090a2505050565b60405162461bcd60e51b81526020600482015260136024820152722932b737bab731b29037b732b6b7b3b7b1b2b760691b60448201526064016107a0565b610e08611702565b6000838152600660205260408120549003610e555760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b60448201526064016107a0565b600083815260066020526040808220919091555183907f72003eda7c2c39777210bccbf69141a92bbe56d746914a16f5ee3aaf5e6f7a8390610e9a9085908590612249565b60405180910390a2505050565b600081815260066020526040812054819081908190808203610ed757600080600080945094509450945050610f0d565b600181610ee762093a808261228e565b834210158015610f035750610eff62093a808561228e565b4211155b9450945094509450505b9193509193565b6009546001600160a01b03163314610f615760405162461bcd60e51b815260206004820152601060248201526f27b7363c902d25903b32b934b334b2b960811b60448201526064016107a0565b6001600160a01b038216610f875760405162461bcd60e51b81526004016107a090612175565b600c54600160a01b900460ff16610fd95760405162461bcd60e51b815260206004820152601660248201527550726f76697a696a61206272657a206b6f76616e6a6160501b60448201526064016107a0565b600c805460ff60a01b19169055610ff0828261190d565b5050565b60606004805461062590612119565b61100b611702565b6110628160405160200161101f91906121d5565b604051602081830303815290604052805190602001206040518060400160405280600f81526020016e525741546f6b656e2e7365744b796360881b8152506117e4565b600d80546001600160a01b0319166001600160a01b0383169081179091556040517f9f5f8fd48aa64bb8a94c00d6adfc92b215610db623c189eb30698be4581265a490600090a250565b600780546110b990612119565b80601f01602080910402602001604051908101604052809291908181526020018280546110e590612119565b80156111325780601f1061110757610100808354040283529160200191611132565b820191906000526020600020905b81548152906001019060200180831161111557829003601f168201915b505050505081565b6000336107f18185856116a3565b6000611152611293565b905090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161580159061121257506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa1580156111ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112129190612153565b6112535760405162461bcd60e51b815260206004820152601260248201527129b0b6b7902aa7a9299037b832b930ba32b960711b60448201526064016107a0565b600d805460ff60a01b1916600160a01b17905560405133907f481d73db1c84a4cd0734a718818b266e3b59f2e485d8ba806e15763777d9d00690600090a2565b600061017146146112a6576102586112ab565b6202a3005b62ffffff16905090565b6112bd611702565b6001600160a01b0381166112e35760405162461bcd60e51b81526004016107a090612175565b611343816040516020016112f7919061219b565b60405160208183030381529060405280519060200120604051806040016040528060188152602001771495d0551bdad95b8b9cd95d119959549958da5c1a595b9d60421b8152506117e4565b600b80546001600160a01b0319166001600160a01b0383169081179091556040517f7a7b5a0a132f9e0581eb8527f66eae9ee89c2a3e79d4ac7e41a1f1f4d48a7fc290600090a250565b611395611702565b6001600160a01b0381166113bf57604051631e4fbdf760e01b8152600060048201526024016107a0565b61092781611943565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661140e5760405162461bcd60e51b81526004016107a090612206565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146114865760405162461bcd60e51b815260206004820152601c60248201527f53616d6f206f7665726974656c6a20746567612073726564737476610000000060448201526064016107a0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161580159061154157506040516338260bcb60e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063704c179690602401602060405180830381865afa15801561151d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115419190612153565b61158d5760405162461bcd60e51b815260206004820152601b60248201527f4f7665726974656c6a206e692076656320706f6f626c617363656e000000000060448201526064016107a0565b6040805160208101829052601060608201526f757064617465417373657456616c756560801b60808201529081018290526109279060a0016040516020818303038152906040528051906020012060405180604001604052806019815260200178525741546f6b656e2e757064617465417373657456616c756560381b815250611731565b61161f8383836001611995565b505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981101561169d578181101561168e57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064016107a0565b61169d84848484036000611995565b50505050565b6001600160a01b0383166116cd57604051634b637e8f60e11b8152600060048201526024016107a0565b6001600160a01b0382166116f75760405163ec442f0560e01b8152600060048201526024016107a0565b61161f838383611a6a565b6005546001600160a01b0316331461172f5760405163118cdaa760e01b81523360048201526024016107a0565b565b6000828152600660205260409020541561177d5760405162461bcd60e51b815260206004820152600d60248201526c5a65206e61706f766564616e6f60981b60448201526064016107a0565b6000611787611293565b611791904261228e565b60008481526006602052604090208190559050827f63a0d065f46e07e30a4f246d28eb53f839982100439173db92dbd5700ab37c1583836117d562093a808261228e565b604051610e9a939291906122a1565b600082815260066020526040812054908190036118335760405162461bcd60e51b815260206004820152600d60248201526c4e69206e61706f766564616e6f60981b60448201526064016107a0565b804210156118795760405162461bcd60e51b815260206004820152601360248201527216985b5a5ac81cd9481b9a481c1bdd195ad95b606a1b60448201526064016107a0565b61188662093a808261228e565b4211156118ca5760405162461bcd60e51b81526020600482015260126024820152714e61706f766564206a6520706f74656b6c6160701b60448201526064016107a0565b600083815260066020526040808220919091555183907ffac4537038ebc9eaa00d86a88a6c2e268012d306f6442966aab36014a195432390610e9a908590611f67565b6001600160a01b0382166119375760405163ec442f0560e01b8152600060048201526024016107a0565b610ff060008383611a6a565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0384166119bf5760405163e602df0560e01b8152600060048201526024016107a0565b6001600160a01b0383166119e957604051634a1406b160e11b8152600060048201526024016107a0565b6001600160a01b038085166000908152600160209081526040808320938716835292905220829055801561169d57826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611a5c91815260200190565b60405180910390a350505050565b600d546001600160a01b03848116159184821615911615611c3b5780158015611aa15750600b546001600160a01b03858116911614155b15611b6057600d54604051633af32abf60e01b81526001600160a01b03868116600483015290911690633af32abf90602401602060405180830381865afa158015611af0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b149190612153565b611b605760405162461bcd60e51b815260206004820152601a60248201527f5072656a656d6e696b206e69204b5943207072657665726a656e00000000000060448201526064016107a0565b81158015611b7c5750600b546001600160a01b03868116911614155b15611c3b57600d54604051633af32abf60e01b81526001600160a01b03878116600483015290911690633af32abf90602401602060405180830381865afa158015611bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bef9190612153565b611c3b5760405162461bcd60e51b815260206004820152601c60248201527f506f73696c6a6174656c6a206e69204b5943207072657665726a656e0000000060448201526064016107a0565b81611d0357600d54600160a01b900460ff1615611c935760405162461bcd60e51b8152602060048201526016602482015275537265647374766f206a65207a616d727a6e6a656e6f60501b60448201526064016107a0565b7f0000000000000000000000000000000000000000000000000000000000000000421015611d035760405162461bcd60e51b815260206004820181905260248201527f537265647374766f207365206e6920616b7469766e6f207a61207072656e6f7360448201526064016107a0565b8180611d0c5750805b80611d245750600b546001600160a01b038681169116145b80611d3c5750600b546001600160a01b038581169116145b15611d5357611d4c858585611df7565b5050505050565b6000612710611d636032866122c6565b611d6d91906122dd565b90506000611d7b82866122ff565b600b54909150611d969088906001600160a01b031684611df7565b611da1878783611df7565b856001600160a01b0316876001600160a01b03167ff403ce23f2694cf9716913477865dd71892b2d8917c097372a485281654fdcb184604051611de691815260200190565b60405180910390a350505050505050565b6001600160a01b038316611e22578060026000828254611e17919061228e565b90915550611e949050565b6001600160a01b03831660009081526020819052604090205481811015611e755760405163391434e360e21b81526001600160a01b038516600482015260248101829052604481018390526064016107a0565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b038216611eb057600280548290039055611ecf565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611f1491815260200190565b60405180910390a3505050565b6000815180845260005b81811015611f4757602081850181015186830182015201611f2b565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000611f7a6020830184611f21565b9392505050565b600060208284031215611f9357600080fd5b5035919050565b80356001600160a01b0381168114611fb157600080fd5b919050565b60008060408385031215611fc957600080fd5b611fd283611f9a565b946020939093013593505050565b600080600060608486031215611ff557600080fd5b611ffe84611f9a565b925061200c60208501611f9a565b9150604084013590509250925092565b60006020828403121561202e57600080fd5b611f7a82611f9a565b60008060006060848603121561204c57600080fd5b61205584611f9a565b95602085013595506040909401359392505050565b60008060006040848603121561207f57600080fd5b83359250602084013567ffffffffffffffff8082111561209e57600080fd5b818601915086601f8301126120b257600080fd5b8135818111156120c157600080fd5b8760208285010111156120d357600080fd5b6020830194508093505050509250925092565b600080604083850312156120f957600080fd5b61210283611f9a565b915061211060208401611f9a565b90509250929050565b600181811c9082168061212d57607f821691505b60208210810361214d57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561216557600080fd5b81518015158114611f7a57600080fd5b6020808252600c908201526b5a65726f206164647265737360a01b604082015260600190565b6040808252600f908201526e1cd95d119959549958da5c1a595b9d608a1b60608201526001600160a01b0391909116602082015260800190565b6040808252600690820152657365744b796360d01b60608201526001600160a01b0391909116602082015260800190565b60208082526023908201527f537265647374766f206e696d61207a61706973616e656761206f7665726974656040820152626c6a6160e81b606082015260800190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156107f7576107f7612278565b6060815260006122b46060830186611f21565b60208301949094525060400152919050565b80820281158282048414176107f7576107f7612278565b6000826122fa57634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156107f7576107f761227856fea264697066735822122034deffb9c10289851c0ded01f317c164e72f10dd6afd348e6ab4769b1ee46a6464736f6c63430008180033a2646970667358221220ce7d6c0af0775c0acfd348ad83e9c16517fcb7eb57396990dd6fb705844d439864736f6c63430008180033