Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- CallistoNFT
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 1000
- EVM Version
- default
- Verified at
- 2024-09-26T15:24:52.583204Z
Contract source code
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/utils/Address.sol
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
// File: xmas/CallistoNFT.sol
pragma solidity ^0.8.12;
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function initializeReentrancyGuard() internal {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
abstract contract MinterRole is Ownable {
mapping (address => bool) public minter_role;
function setMinterRole(address _who, bool _status) public onlyOwner
{
minter_role[_who] = _status;
}
modifier onlyMinter
{
require(minter_role[msg.sender], "Minter role required");
_;
}
}
interface ICallistoNFT {
event NewBid (uint256 indexed tokenID, uint256 indexed bidAmount, bytes data);
event NewPrice (uint256 indexed tokenID, uint256 indexed priceValue, bytes data);
event TokenTrade (uint256 indexed tokenID, address indexed new_owner, address indexed previous_owner, uint256 priceInWEI);
event Transfer (address indexed from, address indexed to, uint256 indexed tokenId);
event TransferData (bytes data);
struct Properties {
// In this example properties of the given NFT are stored
// in a dynamically sized array of strings
// properties can be re-defined for any specific info
// that a particular NFT is intended to store.
/* Properties could look like this:
bytes property1;
bytes property2;
address property3;
*/
string[] properties;
}
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function standard() external view returns (string memory);
function balanceOf(address _who) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function transfer(address _to, uint256 _tokenId, bytes calldata _data) external returns (bool);
function silentTransfer(address _to, uint256 _tokenId) external returns (bool);
function priceOf(uint256 _tokenId) external view returns (uint256);
function bidOf(uint256 _tokenId) external view returns (uint256 price, address payable bidder, uint256 timestamp);
function getTokenProperties(uint256 _tokenId) external view returns (Properties memory);
function setBid(uint256 _tokenId, bytes calldata _data) payable external; // bid amount is defined by msg.value
function setPrice(uint256 _tokenId, uint256 _amountInWEI, bytes calldata _data) external;
function withdrawBid(uint256 _tokenId) external returns (bool);
function getUserContent(uint256 _tokenId) external view returns (string memory _content);
function setUserContent(uint256 _tokenId, string calldata _content) external returns (bool);
}
abstract contract NFTReceiver {
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external virtual returns(bytes4);
}
// ExtendedNFT is a version of the CallistoNFT standard token
// that implements a set of function for NFT content management
contract ExtendedNFT is ICallistoNFT, ReentrancyGuard {
using Address for address;
event TokenPropertyUpdated(uint tokenID, uint propertyID);
mapping (uint256 => Properties) private _tokenProperties;
mapping (uint32 => Fee) public feeLevels; // level # => (fee receiver, fee percentage)
uint256 public bidLock = 1 days; // Time required for a bid to become withdrawable.
struct Bid {
address payable bidder;
uint256 amountInWEI;
uint256 timestamp;
}
struct Fee {
address payable feeReceiver;
uint256 feePercentage; // Will be divided by 100000 during calculations
// feePercentage of 100 means 0.1% fee
// feePercentage of 2500 means 2.5% fee
}
mapping (uint256 => uint256) private _asks; // tokenID => price of this token (in WEI)
mapping (uint256 => Bid) private _bids; // tokenID => price of this token (in WEI)
mapping (uint256 => uint32) internal _tokenFeeLevels; // tokenID => level ID / 0 by default
uint256 public next_mint_id;
// Token name
string internal _name;
// Token symbol
string internal _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) internal _owners;
// Mapping owner address to token count
mapping(address => uint256) internal _balances;
// Reward is always paid based on BID
modifier checkTrade(uint256 _tokenId, bytes calldata _data)
{
_;
(uint256 _bid, address payable _bidder,) = bidOf(_tokenId);
if(priceOf(_tokenId) > 0 && priceOf(_tokenId) <= _bid)
{
uint256 _reward = _bid - _claimFee(_bid, _tokenId);
emit TokenTrade(_tokenId, _bidder, ownerOf(_tokenId), _reward);
bool sent = payable(ownerOf(_tokenId)).send(_reward);
//bytes calldata _empty;
delete _bids[_tokenId];
delete _asks[_tokenId];
_transfer(ownerOf(_tokenId), _bidder, _tokenId, _data);
}
}
function standard() public view virtual override returns (string memory)
{
return "CallistoNFT";
}
function mint() internal returns (uint256 _mintedId)
{
_safeMint(msg.sender, next_mint_id);
_mintedId = next_mint_id;
next_mint_id++;
_configureNFT(_mintedId);
}
function priceOf(uint256 _tokenId) public view virtual override returns (uint256)
{
address owner = _owners[_tokenId];
require(owner != address(0), "NFT: owner query for nonexistent token");
return _asks[_tokenId];
}
function bidOf(uint256 _tokenId) public view virtual override returns (uint256 price, address payable bidder, uint256 timestamp)
{
address owner = _owners[_tokenId];
require(owner != address(0), "NFT: owner query for nonexistent token");
return (_bids[_tokenId].amountInWEI, _bids[_tokenId].bidder, _bids[_tokenId].timestamp);
}
function getTokenProperties(uint256 _tokenId) public view virtual override returns (Properties memory)
{
return _tokenProperties[_tokenId];
}
function getTokenProperty(uint256 _tokenId, uint256 _propertyId) public view virtual returns (string memory)
{
return _tokenProperties[_tokenId].properties[_propertyId];
}
function getUserContent(uint256 _tokenId) public view virtual override returns (string memory _content)
{
return (_tokenProperties[_tokenId].properties[0]);
}
function setUserContent(uint256 _tokenId, string calldata _content) public virtual override returns (bool success)
{
require(msg.sender == ownerOf(_tokenId), "NFT: only owner can change NFT content");
_tokenProperties[_tokenId].properties[0] = _content;
emit TokenPropertyUpdated(_tokenId, 0) ;
return true;
}
function _addPropertyWithContent(uint256 _tokenId, string calldata _content) internal
{
// Check permission criteria
_tokenProperties[_tokenId].properties.push(_content);
uint newPropertyID = _tokenProperties[_tokenId].properties.length - 1;
emit TokenPropertyUpdated(_tokenId, newPropertyID);
}
function _modifyProperty(uint256 _tokenId, uint256 _propertyId, string calldata _content) internal
{
_tokenProperties[_tokenId].properties[_propertyId] = _content;
emit TokenPropertyUpdated(_tokenId, _propertyId);
}
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "NFT: balance query for the zero address");
return _balances[owner];
}
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "NFT: owner query for nonexistent token");
return owner;
}
// Price == 0, "NFT not on sale"
// Price > 0, "NFT on sale"
function setPrice(uint256 _tokenId, uint256 _amountInWEI, bytes calldata _data) checkTrade(_tokenId, _data) public virtual override nonReentrant {
require(ownerOf(_tokenId) == msg.sender, "Setting asks is only allowed for owned NFTs!");
_asks[_tokenId] = _amountInWEI;
emit NewPrice(_tokenId, _amountInWEI, _data);
}
function setBid(uint256 _tokenId, bytes calldata _data) payable checkTrade(_tokenId, _data) public virtual override nonReentrant
{
(uint256 _previousBid, address payable _previousBidder, ) = bidOf(_tokenId);
require(msg.value > _previousBid, "New bid must exceed the existing one");
uint256 _bid;
// Return previous bid if the current one exceeds it.
if(_previousBid != 0)
{
bool sent = _previousBidder.send(_previousBid);
}
// Refund overpaid amount if price is greater than 0
if (priceOf(_tokenId) < msg.value && priceOf(_tokenId) > 0)
{
_bid = priceOf(_tokenId);
}
else
{
_bid = msg.value;
}
_bids[_tokenId].amountInWEI = _bid;
_bids[_tokenId].bidder = payable(msg.sender);
_bids[_tokenId].timestamp = block.timestamp;
emit NewBid(_tokenId, _bid, _data);
// Send back overpaid amount.
// WARNING: Creates possibility for reentrancy.
if (priceOf(_tokenId) < msg.value && priceOf(_tokenId) > 0)
{
bool sent = payable(msg.sender).send(msg.value - priceOf(_tokenId));
}
}
function withdrawBid(uint256 _tokenId) public virtual override nonReentrant returns (bool)
{
(uint256 _bid, address payable _bidder, uint256 _timestamp) = bidOf(_tokenId);
require(msg.sender == _bidder, "Can not withdraw someone elses bid");
require(block.timestamp > _timestamp + bidLock, "Bid is time-locked");
bool sent = _bidder.send(_bid);
delete _bids[_tokenId];
emit NewBid(_tokenId, 0, "0x7769746864726177426964");
return true;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function transfer(address _to, uint256 _tokenId, bytes calldata _data) public override returns (bool)
{
_transfer(msg.sender, _to, _tokenId, _data);
emit TransferData(_data);
return true;
}
function silentTransfer(address _to, uint256 _tokenId) public override returns (bool)
{
require(ExtendedNFT.ownerOf(_tokenId) == msg.sender, "NFT: transfer of token that is not own");
require(_to != address(0), "NFT: transfer to the zero address");
_asks[_tokenId] = 0; // Zero out price on transfer
// When a user transfers the NFT to another user
// it does not automatically mean that the new owner
// would like to sell this NFT at a price
// specified by the previous owner.
// However bids persist regardless of token transfers
// because we assume that the bidder still wants to buy the NFT
// no matter from whom.
_beforeTokenTransfer(msg.sender, _to, _tokenId);
_balances[msg.sender] -= 1;
_balances[_to] += 1;
_owners[_tokenId] = _to;
emit Transfer(msg.sender, _to, _tokenId);
return true;
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
function _claimFee(uint256 _amountFrom, uint256 _tokenId) internal returns (uint256)
{
uint32 _level = _tokenFeeLevels[_tokenId];
address _feeReceiver = feeLevels[_level].feeReceiver;
uint256 _feePercentage = feeLevels[_level].feePercentage;
uint256 _feeAmount = _amountFrom * _feePercentage / 100000;
bool sent = payable(_feeReceiver).send(_feeAmount);
return _feeAmount;
}
function _safeMint(
address to,
uint256 tokenId
) internal virtual {
_mint(to, tokenId);
}
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "NFT: mint to the zero address");
require(!_exists(tokenId), "NFT: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
function _burn(uint256 tokenId) internal virtual {
address owner = ExtendedNFT.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
function _transfer(
address from,
address to,
uint256 tokenId,
bytes calldata data
) internal virtual {
require(ExtendedNFT.ownerOf(tokenId) == from, "NFT: transfer of token that is not own");
require(to != address(0), "NFT: transfer to the zero address");
_asks[tokenId] = 0; // Zero out price on transfer
// When a user transfers the NFT to another user
// it does not automatically mean that the new owner
// would like to sell this NFT at a price
// specified by the previous owner.
// However bids persist regardless of token transfers
// because we assume that the bidder still wants to buy the NFT
// no matter from whom.
_beforeTokenTransfer(from, to, tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
if(to.isContract())
{
NFTReceiver(to).onERC721Received(msg.sender, from, tokenId, data);
}
emit Transfer(from, to, tokenId);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
function _configureNFT(uint256 _tokenId) internal
{
if(_tokenProperties[_tokenId].properties.length == 0)
{
_tokenProperties[_tokenId].properties.push("");
}
}
}
interface IClassifiedNFT is ICallistoNFT {
function addNewTokenClass(uint32 _feeLevel, string memory _content) external;
function addClassProperty(uint256 _classID, string memory _content) external;
function modifyClassProperty(uint256 _classID, uint256 _propertyID, string memory _content) external;
function getClassProperty(uint256 _classID, uint256 _propertyID) external view returns (string memory);
function getClassProperties(uint256 _classID) external view returns (string[] memory);
function getClassForTokenID(uint256 _tokenID) external view returns (uint256);
function getClassPropertyForTokenID(uint256 _tokenID, uint256 _propertyID) external view returns (string memory);
function getClassPropertiesForTokenID(uint256 _tokenID) external view returns (string[] memory);
function setClassForTokenID(uint256 _tokenID, uint256 _tokenClass) external;
function mintWithClass(uint256 classId) external returns (uint256 _newTokenID);
}
abstract contract ClassifiedNFT is MinterRole, ExtendedNFT, IClassifiedNFT {
using Address for address;
event ClassPropertyUpdated(uint classID, uint propertyID);
event TokenClassChanged(uint _tokenID, uint _tokenClass);
mapping (uint256 => string[]) public class_properties;
mapping (uint256 => uint32) public class_feeLevel;
mapping (uint256 => uint256) public token_classes;
uint256 public nextClassIndex = 0;
modifier onlyExistingClasses(uint256 classId)
{
require(classId < nextClassIndex, "Queried class does not exist");
_;
}
function addNewTokenClass(uint32 _feeLevel, string memory _content) public onlyOwner override
{
class_properties[nextClassIndex].push(_content);
class_feeLevel[nextClassIndex] = _feeLevel; // Configures who will receive fees from this class of NFTs
// Zero sets fees to default address and percentage.
emit ClassPropertyUpdated(nextClassIndex, 0);
nextClassIndex++;
}
function addClassProperty(uint256 _classID, string memory _content) public onlyOwner onlyExistingClasses(_classID)
{
class_properties[_classID].push(_content);
uint newPropertyID = class_properties[_classID].length - 1;
emit ClassPropertyUpdated(_classID, newPropertyID);
}
function modifyClassProperty(uint256 _classID, uint256 _propertyID, string memory _content) public onlyOwner onlyExistingClasses(_classID) override
{
class_properties[_classID][_propertyID] = _content;
emit ClassPropertyUpdated(_classID, _propertyID);
}
function getClassProperty(uint256 _classID, uint256 _propertyID) public view onlyExistingClasses(_classID) override returns (string memory)
{
return class_properties[_classID][_propertyID];
}
function getClassProperties(uint256 _classID) public view onlyExistingClasses(_classID) override returns (string[] memory)
{
return class_properties[_classID];
}
function getClassForTokenID(uint256 _tokenID) public view onlyExistingClasses(token_classes[_tokenID]) override returns (uint256)
{
return token_classes[_tokenID];
}
function getClassPropertyForTokenID(uint256 _tokenID, uint256 _propertyID) public view onlyExistingClasses(token_classes[_tokenID]) override returns (string memory)
{
return class_properties[token_classes[_tokenID]][_propertyID];
}
function getClassPropertiesForTokenID(uint256 _tokenID) public view onlyExistingClasses(token_classes[_tokenID]) override returns (string[] memory)
{
return class_properties[token_classes[_tokenID]];
}
function setClassForTokenID(uint256 _tokenID, uint256 _tokenClass) public onlyOwner override
{
token_classes[_tokenID] = _tokenClass;
emit TokenClassChanged(_tokenID, _tokenClass);
}
function mintWithClass(uint256 classId) public onlyExistingClasses(classId) onlyMinter override returns (uint256 _newTokenID)
{
_newTokenID = mint();
token_classes[_newTokenID] = classId;
_tokenFeeLevels[_newTokenID] = class_feeLevel[classId];
}
}
contract CallistoNFT is ExtendedNFT, ClassifiedNFT {
function initialize(string memory name_, string memory symbol_, uint256 _defaultFee) external {
require(owner() == address(0), "Already initialized");
_transferOwnership(msg.sender);
initializeReentrancyGuard();
bidLock = 1 days;
_name = name_;
_symbol = symbol_;
feeLevels[0].feeReceiver = payable(msg.sender);
feeLevels[0].feePercentage = _defaultFee;
}
function setFeeLevel(uint32 _levelIndex, address _feeReceiver, uint256 _feePercentage) public onlyOwner
{
feeLevels[_levelIndex].feeReceiver = payable(_feeReceiver);
feeLevels[_levelIndex].feePercentage = _feePercentage;
}
function setFeeLevelForToken(uint256 _tokenId, uint32 _feeLevel) public onlyOwner
{
_tokenFeeLevels[_tokenId] = _feeLevel;
}
function modifyClassFeeLevel(uint256 _classId, uint32 _feeLevel) public onlyOwner
{
class_feeLevel[_classId] = _feeLevel;
}
function addPropertyWithContent(uint256 _tokenId, string calldata _content) public /* onlyOwner or Minter */
{
require(owner() == msg.sender || minter_role[msg.sender], "Ownable: caller is not the owner");
_addPropertyWithContent( _tokenId, _content);
}
function modifyProperty(uint256 _tokenId, uint256 _propertyId, string calldata _content) public onlyOwner
{
_modifyProperty(_tokenId, _propertyId, _content);
}
}
Contract ABI
[{"type":"event","name":"ClassPropertyUpdated","inputs":[{"type":"uint256","name":"classID","internalType":"uint256","indexed":false},{"type":"uint256","name":"propertyID","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewBid","inputs":[{"type":"uint256","name":"tokenID","internalType":"uint256","indexed":true},{"type":"uint256","name":"bidAmount","internalType":"uint256","indexed":true},{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"NewPrice","inputs":[{"type":"uint256","name":"tokenID","internalType":"uint256","indexed":true},{"type":"uint256","name":"priceValue","internalType":"uint256","indexed":true},{"type":"bytes","name":"data","internalType":"bytes","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":"TokenClassChanged","inputs":[{"type":"uint256","name":"_tokenID","internalType":"uint256","indexed":false},{"type":"uint256","name":"_tokenClass","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenPropertyUpdated","inputs":[{"type":"uint256","name":"tokenID","internalType":"uint256","indexed":false},{"type":"uint256","name":"propertyID","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenTrade","inputs":[{"type":"uint256","name":"tokenID","internalType":"uint256","indexed":true},{"type":"address","name":"new_owner","internalType":"address","indexed":true},{"type":"address","name":"previous_owner","internalType":"address","indexed":true},{"type":"uint256","name":"priceInWEI","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"TransferData","inputs":[{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addClassProperty","inputs":[{"type":"uint256","name":"_classID","internalType":"uint256"},{"type":"string","name":"_content","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addNewTokenClass","inputs":[{"type":"uint32","name":"_feeLevel","internalType":"uint32"},{"type":"string","name":"_content","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addPropertyWithContent","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"string","name":"_content","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"bidLock","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"price","internalType":"uint256"},{"type":"address","name":"bidder","internalType":"address payable"},{"type":"uint256","name":"timestamp","internalType":"uint256"}],"name":"bidOf","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"class_feeLevel","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"class_properties","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"feeReceiver","internalType":"address payable"},{"type":"uint256","name":"feePercentage","internalType":"uint256"}],"name":"feeLevels","inputs":[{"type":"uint32","name":"","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getClassForTokenID","inputs":[{"type":"uint256","name":"_tokenID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string[]","name":"","internalType":"string[]"}],"name":"getClassProperties","inputs":[{"type":"uint256","name":"_classID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string[]","name":"","internalType":"string[]"}],"name":"getClassPropertiesForTokenID","inputs":[{"type":"uint256","name":"_tokenID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getClassProperty","inputs":[{"type":"uint256","name":"_classID","internalType":"uint256"},{"type":"uint256","name":"_propertyID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getClassPropertyForTokenID","inputs":[{"type":"uint256","name":"_tokenID","internalType":"uint256"},{"type":"uint256","name":"_propertyID","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct ICallistoNFT.Properties","components":[{"type":"string[]","name":"properties","internalType":"string[]"}]}],"name":"getTokenProperties","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"getTokenProperty","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"uint256","name":"_propertyId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"_content","internalType":"string"}],"name":"getUserContent","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"},{"type":"uint256","name":"_defaultFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"_newTokenID","internalType":"uint256"}],"name":"mintWithClass","inputs":[{"type":"uint256","name":"classId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"minter_role","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"modifyClassFeeLevel","inputs":[{"type":"uint256","name":"_classId","internalType":"uint256"},{"type":"uint32","name":"_feeLevel","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"modifyClassProperty","inputs":[{"type":"uint256","name":"_classID","internalType":"uint256"},{"type":"uint256","name":"_propertyID","internalType":"uint256"},{"type":"string","name":"_content","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"modifyProperty","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"uint256","name":"_propertyId","internalType":"uint256"},{"type":"string","name":"_content","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nextClassIndex","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"next_mint_id","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ownerOf","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"priceOf","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"setBid","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setClassForTokenID","inputs":[{"type":"uint256","name":"_tokenID","internalType":"uint256"},{"type":"uint256","name":"_tokenClass","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeLevel","inputs":[{"type":"uint32","name":"_levelIndex","internalType":"uint32"},{"type":"address","name":"_feeReceiver","internalType":"address"},{"type":"uint256","name":"_feePercentage","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeLevelForToken","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"uint32","name":"_feeLevel","internalType":"uint32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinterRole","inputs":[{"type":"address","name":"_who","internalType":"address"},{"type":"bool","name":"_status","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPrice","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"uint256","name":"_amountInWEI","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"success","internalType":"bool"}],"name":"setUserContent","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"string","name":"_content","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"silentTransfer","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"standard","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"token_classes","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"withdrawBid","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]}]
Contract Creation Code
0x608060405262015180600555600060115534801561001c57600080fd5b506134118061002c6000396000f3fe6080604052600436106102e75760003560e01c8063715018a611610184578063b9186d7d116100d6578063c98e0c3c1161008a578063e29fb03611610064578063e29fb036146108fd578063e647005914610913578063f2fde38b1461093357600080fd5b8063c98e0c3c14610875578063cb177b1e14610895578063d75d1e66146108b557600080fd5b8063be45fd62116100bb578063be45fd6214610808578063c180f4f114610828578063c1940f1b1461084857600080fd5b8063b9186d7d146107c8578063bb053717146107e857600080fd5b80638da5cb5b1161013857806395d89b411161011257806395d89b41146107735780639de4792e14610788578063b119490e146107a857600080fd5b80638da5cb5b1461071f5780638e39e18c1461073d578063911006951461075d57600080fd5b806374c29ce31161016957806374c29ce31461068057806378317f3f146106df5780637ab56e52146106ff57600080fd5b8063715018a61461065857806373baa6511461066d57600080fd5b80633e0bb7831161023d578063543dc7fa116101f1578063648fbe40116101cb578063648fbe40146105d5578063649ccc14146105f557806370a082311461063857600080fd5b8063543dc7fa146105375780635a3b7e42146105575780636352211e1461059d57600080fd5b80634c1720a4116102225780634c1720a4146104ba5780634edea111146104da578063510910bb1461050757600080fd5b80633e0bb7831461046d5780634bb2ddd41461048d57600080fd5b806325498c751161029f5780633054d9cb116102795780633054d9cb1461040d5780633c65b3eb1461042d5780633d8073f11461044d57600080fd5b806325498c75146103ad578063290e008c146103cd5780632a6d3f44146103ed57600080fd5b80630eaaf4c8116102d05780630eaaf4c8146103375780631d734c8f146103675780631f38e6541461038b57600080fd5b806302ff368a146102ec57806306fdde0314610322575b600080fd5b3480156102f857600080fd5b5061030c610307366004612b19565b610953565b6040516103199190612b78565b60405180910390f35b34801561032e57600080fd5b5061030c610a0d565b34801561034357600080fd5b50610357610352366004612b19565b610a9f565b6040519015158152602001610319565b34801561037357600080fd5b5061037d60115481565b604051908152602001610319565b34801561039757600080fd5b506103ab6103a6366004612b92565b610c6f565b005b3480156103b957600080fd5b506103ab6103c8366004612c6b565b610cc6565b3480156103d957600080fd5b506103ab6103e8366004612d02565b610d7b565b3480156103f957600080fd5b50610357610408366004612d02565b610e0e565b34801561041957600080fd5b506103ab610428366004612d4e565b610f1b565b34801561043957600080fd5b5061037d610448366004612b19565b610fef565b34801561045957600080fd5b506103ab610468366004612d9e565b6110f3565b34801561047957600080fd5b5061030c610488366004612b92565b61130f565b34801561049957600080fd5b506104ad6104a8366004612b19565b6113c8565b6040516103199190612e46565b3480156104c657600080fd5b5061030c6104d5366004612b92565b611518565b3480156104e657600080fd5b506104fa6104f5366004612b19565b611628565b6040516103199190612e59565b34801561051357600080fd5b50610357610522366004612e93565b60016020526000908152604090205460ff1681565b34801561054357600080fd5b5061037d610552366004612b19565b61171d565b34801561056357600080fd5b5060408051808201909152600b81527f43616c6c6973746f4e4654000000000000000000000000000000000000000000602082015261030c565b3480156105a957600080fd5b506105bd6105b8366004612b19565b611791565b6040516001600160a01b039091168152602001610319565b3480156105e157600080fd5b506103ab6105f0366004612eae565b61180b565b34801561060157600080fd5b50610615610610366004612b19565b61183b565b604080519384526001600160a01b03909216602084015290820152606001610319565b34801561064457600080fd5b5061037d610653366004612e93565b6118e2565b34801561066457600080fd5b506103ab61197c565b6103ab61067b366004612d02565b611990565b34801561068c57600080fd5b506106c061069b366004612eda565b600460205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b039093168352602083019190915201610319565b3480156106eb57600080fd5b506103ab6106fa366004612eae565b611c7d565b34801561070b57600080fd5b5061030c61071a366004612b92565b611cad565b34801561072b57600080fd5b506000546001600160a01b03166105bd565b34801561074957600080fd5b506103ab610758366004612ef5565b611d6c565b34801561076957600080fd5b5061037d60055481565b34801561077f57600080fd5b5061030c611daf565b34801561079457600080fd5b5061030c6107a3366004612b92565b611dbe565b3480156107b457600080fd5b506103ab6107c3366004612f31565b611e4f565b3480156107d457600080fd5b5061037d6107e3366004612b19565b611f3c565b3480156107f457600080fd5b506103ab610803366004612d9e565b611fc4565b34801561081457600080fd5b50610357610823366004612f9e565b611fde565b34801561083457600080fd5b506103ab610843366004612fe0565b612031565b34801561085457600080fd5b5061037d610863366004612b19565b60106020526000908152604090205481565b34801561088157600080fd5b50610357610890366004613011565b612108565b3480156108a157600080fd5b506103ab6108b036600461303b565b612299565b3480156108c157600080fd5b506108e86108d0366004612b19565b600f6020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001610319565b34801561090957600080fd5b5061037d60095481565b34801561091f57600080fd5b506104ad61092e366004612b19565b6122cc565b34801561093f57600080fd5b506103ab61094e366004612e93565b6123f5565b600081815260036020526040812080546060929061097357610973613077565b9060005260206000200180546109889061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546109b49061308d565b8015610a015780601f106109d657610100808354040283529160200191610a01565b820191906000526020600020905b8154815290600101906020018083116109e457829003601f168201915b50505050509050919050565b6060600a8054610a1c9061308d565b80601f0160208091040260200160405190810160405280929190818152602001828054610a489061308d565b8015610a955780601f10610a6a57610100808354040283529160200191610a95565b820191906000526020600020905b815481529060010190602001808311610a7857829003601f168201915b5050505050905090565b6000610aa9612485565b6000806000610ab78561183b565b91945092509050336001600160a01b03831614610b415760405162461bcd60e51b815260206004820152602260248201527f43616e206e6f7420776974686472617720736f6d656f6e6520656c736573206260448201527f696400000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600554610b4e90826130d7565b4211610b9c5760405162461bcd60e51b815260206004820152601260248201527f4269642069732074696d652d6c6f636b656400000000000000000000000000006044820152606401610b38565b6040516000906001600160a01b0384169085156108fc0290869084818181858888f160008b81526007602052604080822080546001600160a01b0319168155600181018390556002018290555191965094508a93507f223d0d5db4846341da7a5cc902b1a7c597e63b6c73b1c6267dc931d290c7affb9250610c50915060208082526018908201527f3078373736393734363836343732363137373432363936340000000000000000604082015260600190565b60405180910390a36001945050505050610c6a6001600255565b919050565b610c776124dc565b60008281526010602090815260409182902083905581518481529081018390527fa8b2c0f94a578b5a88c9c7d9242237165ea684a64cd32968c7f0dd6edd22dbe0910160405180910390a15050565b610cce6124dc565b6011546000908152600e6020908152604082208054600181018255908352912001610cf98282613138565b50601180546000908152600f6020526040808220805463ffffffff871663ffffffff19909116179055915491517f949a1ec513916b5e46ab2c5681369a4651bba074831b8da896b06a94e8d041b692610d5a92908252602082015260400190565b60405180910390a160118054906000610d72836131f8565b91905055505050565b33610d8e6000546001600160a01b031690565b6001600160a01b03161480610db257503360009081526001602052604090205460ff165b610dfe5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b38565b610e09838383612536565b505050565b6000610e1984611791565b6001600160a01b0316336001600160a01b031614610e9f5760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f6e6c79206f776e65722063616e206368616e6765204e4654206360448201527f6f6e74656e7400000000000000000000000000000000000000000000000000006064820152608401610b38565b600084815260036020526040812080548592859291610ec057610ec0613077565b906000526020600020019182610ed7929190613211565b5060408051858152600060208201527f0fe79316286f6a1e5cf32c3c4ff10c2a66b9cd66da3353db3789c4042ffb44ee910160405180910390a15060019392505050565b610f236124dc565b826011548110610f755760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000848152600e60205260409020805483919085908110610f9857610f98613077565b906000526020600020019081610fae9190613138565b5060408051858152602081018590527f949a1ec513916b5e46ab2c5681369a4651bba074831b8da896b06a94e8d041b691015b60405180910390a150505050565b60008160115481106110435760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b3360009081526001602052604090205460ff166110a25760405162461bcd60e51b815260206004820152601460248201527f4d696e74657220726f6c652072657175697265640000000000000000000000006044820152606401610b38565b6110aa6125b4565b6000818152601060209081526040808320879055958252600f8152858220548383526008909152949020805463ffffffff191663ffffffff909516949094179093555090919050565b8382826110fe612485565b3361110888611791565b6001600160a01b0316146111845760405162461bcd60e51b815260206004820152602c60248201527f53657474696e672061736b73206973206f6e6c7920616c6c6f77656420666f7260448201527f206f776e6564204e4654732100000000000000000000000000000000000000006064820152608401610b38565b6000878152600660205260409081902087905551869088907f403cbda48c4d379b57469bea093b63817816d893b467842ee46fd1c3c29c05f8906111cb90899089906132fb565b60405180910390a36111dd6001600255565b6000806111e98561183b565b509150915060006111f986611f3c565b11801561120e57508161120b86611f3c565b11155b1561130457600061121f83876125e6565b611229908461330f565b905061123486611791565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a38460405161127991815260200190565b60405180910390a4600061128c87611791565b6001600160a01b03166108fc839081150290604051600060405180830381858888f160008c815260076020908152604080832080546001600160a01b0319168155600181018490556002018390556006909152812055945061130193506112f892508a91506117919050565b8489898961266d565b50505b505050505050505050565b600e602052816000526040600020818154811061132b57600080fd5b906000526020600020016000915091505080546113479061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546113739061308d565b80156113c05780601f10611395576101008083540402835291602001916113c0565b820191906000526020600020905b8154815290600101906020018083116113a357829003601f168201915b505050505081565b60008181526010602052604090205460115460609190811061142c5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000838152601060209081526040808320548352600e825280832080548251818502810185019093528083529193909284015b8282101561150b57838290600052602060002001805461147e9061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546114aa9061308d565b80156114f75780601f106114cc576101008083540402835291602001916114f7565b820191906000526020600020905b8154815290600101906020018083116114da57829003601f168201915b50505050508152602001906001019061145f565b5050505091505b50919050565b606082601154811061156c5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000848152600e6020526040902080548490811061158c5761158c613077565b9060005260206000200180546115a19061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546115cd9061308d565b801561161a5780601f106115ef5761010080835404028352916020019161161a565b820191906000526020600020905b8154815290600101906020018083116115fd57829003601f168201915b505050505091505092915050565b604080516020808201835260608252600084815260038252838120845181548085028201870187529381018481529495909491938593859285015b8282101561170f5783829060005260206000200180546116829061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546116ae9061308d565b80156116fb5780601f106116d0576101008083540402835291602001916116fb565b820191906000526020600020905b8154815290600101906020018083116116de57829003601f168201915b505050505081526020019060010190611663565b505050915250909392505050565b600081815260106020526040812054601154811061177d5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b505060009081526010602052604090205490565b6000818152600c60205260408120546001600160a01b0316806118055760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604482015265103a37b5b2b760d11b6064820152608401610b38565b92915050565b6118136124dc565b600091825260086020526040909120805463ffffffff191663ffffffff909216919091179055565b6000818152600c6020526040812054819081906001600160a01b0316806118b35760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604482015265103a37b5b2b760d11b6064820152608401610b38565b5050506000918252506007602052604090206001810154815460029092015490926001600160a01b0390921691565b60006001600160a01b0382166119605760405162461bcd60e51b815260206004820152602760248201527f4e46543a2062616c616e636520717565727920666f7220746865207a65726f2060448201527f61646472657373000000000000000000000000000000000000000000000000006064820152608401610b38565b506001600160a01b03166000908152600d602052604090205490565b6119846124dc565b61198e60006128ba565b565b82828261199b612485565b6000806119a78861183b565b5091509150813411611a205760405162461bcd60e51b8152602060048201526024808201527f4e657720626964206d7573742065786365656420746865206578697374696e6760448201527f206f6e65000000000000000000000000000000000000000000000000000000006064820152608401610b38565b60008215611a51576040516000906001600160a01b0384169085156108fc0290869084818181858888f15050505050505b34611a5b8a611f3c565b108015611a7057506000611a6e8a611f3c565b115b15611a8557611a7e89611f3c565b9050611a88565b50345b600089815260076020526040908190206001810183905580546001600160a01b03191633178155426002909101555181908a907f223d0d5db4846341da7a5cc902b1a7c597e63b6c73b1c6267dc931d290c7affb90611aea908c908c906132fb565b60405180910390a334611afc8a611f3c565b108015611b1157506000611b0f8a611f3c565b115b15611b48576000336108fc611b258c611f3c565b611b2f903461330f565b6040518115909202916000818181858888f15050505050505b505050611b556001600255565b600080611b618561183b565b50915091506000611b7186611f3c565b118015611b86575081611b8386611f3c565b11155b15611c73576000611b9783876125e6565b611ba1908461330f565b9050611bac86611791565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a384604051611bf191815260200190565b60405180910390a46000611c0487611791565b6001600160a01b03166108fc839081150290604051600060405180830381858888f160008c815260076020908152604080832080546001600160a01b03191681556001810184905560020183905560069091528120559450611c7093506112f892508a91506117919050565b50505b5050505050505050565b611c856124dc565b6000918252600f6020526040909120805463ffffffff191663ffffffff909216919091179055565b600082815260036020526040902080546060919083908110611cd157611cd1613077565b906000526020600020018054611ce69061308d565b80601f0160208091040260200160405190810160405280929190818152602001828054611d129061308d565b8015611d5f5780601f10611d3457610100808354040283529160200191611d5f565b820191906000526020600020905b815481529060010190602001808311611d4257829003601f168201915b5050505050905092915050565b611d746124dc565b63ffffffff909216600090815260046020526040902080546001600160a01b039092166001600160a01b031990921691909117815560010155565b6060600b8054610a1c9061308d565b600082815260106020526040902054601154606091908110611e225760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000848152601060209081526040808320548352600e909152902080548490811061158c5761158c613077565b6000546001600160a01b031615611ea85760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610b38565b611eb1336128ba565b611ebb6001600255565b62015180600555600a611ece8482613138565b50600b611edb8382613138565b506000805260046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec80546001600160a01b031916331790557f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ed555050565b6000818152600c60205260408120546001600160a01b031680611fb05760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604482015265103a37b5b2b760d11b6064820152608401610b38565b505060009081526006602052604090205490565b611fcc6124dc565b611fd88484848461290a565b50505050565b6000611fed338686868661266d565b7f3ba9136826ac751de05d770d8d34fa4440ada49a5fb0e9aa1678aece66dad976838360405161201e9291906132fb565b60405180910390a1506001949350505050565b6120396124dc565b81601154811061208b5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000838152600e60209081526040822080546001810182559083529120016120b38382613138565b506000838152600e60205260408120546120cf9060019061330f565b60408051868152602081018390529192507f949a1ec513916b5e46ab2c5681369a4651bba074831b8da896b06a94e8d041b69101610fe1565b60003361211483611791565b6001600160a01b0316146121795760405162461bcd60e51b815260206004820152602660248201527f4e46543a207472616e73666572206f6620746f6b656e2074686174206973206e60448201526537ba1037bbb760d11b6064820152608401610b38565b6001600160a01b0383166121d95760405162461bcd60e51b815260206004820152602160248201527f4e46543a207472616e7366657220746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610b38565b600082815260066020526040812055336000908152600d6020526040812080546001929061220890849061330f565b90915550506001600160a01b0383166000908152600d602052604081208054600192906122369084906130d7565b90915550506000828152600c602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a450600192915050565b6122a16124dc565b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b60608160115481106123205760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000838152600e6020908152604080832080548251818502810185019093528083529193909284015b8282101561150b5783829060005260206000200180546123689061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546123949061308d565b80156123e15780601f106123b6576101008083540402835291602001916123e1565b820191906000526020600020905b8154815290600101906020018083116123c457829003601f168201915b505050505081526020019060010190612349565b6123fd6124dc565b6001600160a01b0381166124795760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b38565b612482816128ba565b50565b60028054036124d65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b38565b60028055565b6000546001600160a01b0316331461198e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b38565b60008381526003602090815260408220805460018101825590835291200161255f828483613211565b5060008381526003602052604081205461257b9060019061330f565b60408051868152602081018390529192507f0fe79316286f6a1e5cf32c3c4ff10c2a66b9cd66da3353db3789c4042ffb44ee9101610fe1565b60006125c23360095461297c565b506009805490819060006125d5836131f8565b91905055506125e38161298a565b90565b60008181526008602090815260408083205463ffffffff168084526004909252822080546001909101546001600160a01b039091169083620186a061262b8389613322565b6126359190613339565b90506000836001600160a01b03166108fc839081150290604051600060405180830381858888f150949b9a5050505050505050505050565b846001600160a01b031661268084611791565b6001600160a01b0316146126e55760405162461bcd60e51b815260206004820152602660248201527f4e46543a207472616e73666572206f6620746f6b656e2074686174206973206e60448201526537ba1037bbb760d11b6064820152608401610b38565b6001600160a01b0384166127455760405162461bcd60e51b815260206004820152602160248201527f4e46543a207472616e7366657220746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610b38565b6000838152600660205260408120556001600160a01b0385166000908152600d6020526040812080546001929061277d90849061330f565b90915550506001600160a01b0384166000908152600d602052604081208054600192906127ab9084906130d7565b90915550506000838152600c6020526040902080546001600160a01b0319166001600160a01b0386169081179091553b15612872576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a029061282d903390899088908890889060040161335b565b6020604051808303816000875af115801561284c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128709190613399565b505b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008481526003602052604090208054839183918690811061292e5761292e613077565b906000526020600020019182612945929190613211565b5060408051858152602081018590527f0fe79316286f6a1e5cf32c3c4ff10c2a66b9cd66da3353db3789c4042ffb44ee9101610fe1565b61298682826129d7565b5050565b600081815260036020526040812054900361248257600081815260036020908152604080832080546001810182559084528284208251938401909252928252909101906129869082613138565b6001600160a01b038216612a2d5760405162461bcd60e51b815260206004820152601d60248201527f4e46543a206d696e7420746f20746865207a65726f20616464726573730000006044820152606401610b38565b6000818152600c60205260409020546001600160a01b031615612a925760405162461bcd60e51b815260206004820152601960248201527f4e46543a20746f6b656e20616c7265616479206d696e746564000000000000006044820152606401610b38565b6001600160a01b0382166000908152600d60205260408120805460019290612abb9084906130d7565b90915550506000818152600c602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600060208284031215612b2b57600080fd5b5035919050565b6000815180845260005b81811015612b5857602081850181015186830182015201612b3c565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612b8b6020830184612b32565b9392505050565b60008060408385031215612ba557600080fd5b50508035926020909101359150565b803563ffffffff81168114610c6a57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f830112612bef57600080fd5b813567ffffffffffffffff80821115612c0a57612c0a612bc8565b604051601f8301601f19908116603f01168101908282118183101715612c3257612c32612bc8565b81604052838152866020858801011115612c4b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612c7e57600080fd5b612c8783612bb4565b9150602083013567ffffffffffffffff811115612ca357600080fd5b612caf85828601612bde565b9150509250929050565b60008083601f840112612ccb57600080fd5b50813567ffffffffffffffff811115612ce357600080fd5b602083019150836020828501011115612cfb57600080fd5b9250929050565b600080600060408486031215612d1757600080fd5b83359250602084013567ffffffffffffffff811115612d3557600080fd5b612d4186828701612cb9565b9497909650939450505050565b600080600060608486031215612d6357600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612d8857600080fd5b612d9486828701612bde565b9150509250925092565b60008060008060608587031215612db457600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612dd957600080fd5b612de587828801612cb9565b95989497509550505050565b600081518084526020808501808196508360051b8101915082860160005b85811015612e39578284038952612e27848351612b32565b98850198935090840190600101612e0f565b5091979650505050505050565b602081526000612b8b6020830184612df1565b6020815260008251602080840152612e746040840182612df1565b949350505050565b80356001600160a01b0381168114610c6a57600080fd5b600060208284031215612ea557600080fd5b612b8b82612e7c565b60008060408385031215612ec157600080fd5b82359150612ed160208401612bb4565b90509250929050565b600060208284031215612eec57600080fd5b612b8b82612bb4565b600080600060608486031215612f0a57600080fd5b612f1384612bb4565b9250612f2160208501612e7c565b9150604084013590509250925092565b600080600060608486031215612f4657600080fd5b833567ffffffffffffffff80821115612f5e57600080fd5b612f6a87838801612bde565b94506020860135915080821115612f8057600080fd5b50612f8d86828701612bde565b925050604084013590509250925092565b60008060008060608587031215612fb457600080fd5b612fbd85612e7c565b935060208501359250604085013567ffffffffffffffff811115612dd957600080fd5b60008060408385031215612ff357600080fd5b82359150602083013567ffffffffffffffff811115612ca357600080fd5b6000806040838503121561302457600080fd5b61302d83612e7c565b946020939093013593505050565b6000806040838503121561304e57600080fd5b61305783612e7c565b91506020830135801515811461306c57600080fd5b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806130a157607f821691505b60208210810361151257634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115611805576118056130c1565b601f821115610e0957600081815260208120601f850160051c810160208610156131115750805b601f850160051c820191505b818110156131305782815560010161311d565b505050505050565b815167ffffffffffffffff81111561315257613152612bc8565b61316681613160845461308d565b846130ea565b602080601f83116001811461319b57600084156131835750858301515b600019600386901b1c1916600185901b178555613130565b600085815260208120601f198616915b828110156131ca578886015182559484019460019091019084016131ab565b50858210156131e85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161320a5761320a6130c1565b5060010190565b67ffffffffffffffff83111561322957613229612bc8565b61323d83613237835461308d565b836130ea565b6000601f84116001811461327157600085156132595750838201355b600019600387901b1c1916600186901b1783556132cb565b600083815260209020601f19861690835b828110156132a25786850135825560209485019460019092019101613282565b50868210156132bf5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000612e746020830184866132d2565b81810381811115611805576118056130c1565b8082028115828204841417611805576118056130c1565b60008261335657634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160a01b0380881683528087166020840152508460408301526080606083015261338e6080830184866132d2565b979650505050505050565b6000602082840312156133ab57600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612b8b57600080fdfea2646970667358221220b635039b0e2cc6145666b32639c81a57775ad7ed40f25b6d93eb73b0f790298764736f6c63430008130033
Deployed ByteCode
0x6080604052600436106102e75760003560e01c8063715018a611610184578063b9186d7d116100d6578063c98e0c3c1161008a578063e29fb03611610064578063e29fb036146108fd578063e647005914610913578063f2fde38b1461093357600080fd5b8063c98e0c3c14610875578063cb177b1e14610895578063d75d1e66146108b557600080fd5b8063be45fd62116100bb578063be45fd6214610808578063c180f4f114610828578063c1940f1b1461084857600080fd5b8063b9186d7d146107c8578063bb053717146107e857600080fd5b80638da5cb5b1161013857806395d89b411161011257806395d89b41146107735780639de4792e14610788578063b119490e146107a857600080fd5b80638da5cb5b1461071f5780638e39e18c1461073d578063911006951461075d57600080fd5b806374c29ce31161016957806374c29ce31461068057806378317f3f146106df5780637ab56e52146106ff57600080fd5b8063715018a61461065857806373baa6511461066d57600080fd5b80633e0bb7831161023d578063543dc7fa116101f1578063648fbe40116101cb578063648fbe40146105d5578063649ccc14146105f557806370a082311461063857600080fd5b8063543dc7fa146105375780635a3b7e42146105575780636352211e1461059d57600080fd5b80634c1720a4116102225780634c1720a4146104ba5780634edea111146104da578063510910bb1461050757600080fd5b80633e0bb7831461046d5780634bb2ddd41461048d57600080fd5b806325498c751161029f5780633054d9cb116102795780633054d9cb1461040d5780633c65b3eb1461042d5780633d8073f11461044d57600080fd5b806325498c75146103ad578063290e008c146103cd5780632a6d3f44146103ed57600080fd5b80630eaaf4c8116102d05780630eaaf4c8146103375780631d734c8f146103675780631f38e6541461038b57600080fd5b806302ff368a146102ec57806306fdde0314610322575b600080fd5b3480156102f857600080fd5b5061030c610307366004612b19565b610953565b6040516103199190612b78565b60405180910390f35b34801561032e57600080fd5b5061030c610a0d565b34801561034357600080fd5b50610357610352366004612b19565b610a9f565b6040519015158152602001610319565b34801561037357600080fd5b5061037d60115481565b604051908152602001610319565b34801561039757600080fd5b506103ab6103a6366004612b92565b610c6f565b005b3480156103b957600080fd5b506103ab6103c8366004612c6b565b610cc6565b3480156103d957600080fd5b506103ab6103e8366004612d02565b610d7b565b3480156103f957600080fd5b50610357610408366004612d02565b610e0e565b34801561041957600080fd5b506103ab610428366004612d4e565b610f1b565b34801561043957600080fd5b5061037d610448366004612b19565b610fef565b34801561045957600080fd5b506103ab610468366004612d9e565b6110f3565b34801561047957600080fd5b5061030c610488366004612b92565b61130f565b34801561049957600080fd5b506104ad6104a8366004612b19565b6113c8565b6040516103199190612e46565b3480156104c657600080fd5b5061030c6104d5366004612b92565b611518565b3480156104e657600080fd5b506104fa6104f5366004612b19565b611628565b6040516103199190612e59565b34801561051357600080fd5b50610357610522366004612e93565b60016020526000908152604090205460ff1681565b34801561054357600080fd5b5061037d610552366004612b19565b61171d565b34801561056357600080fd5b5060408051808201909152600b81527f43616c6c6973746f4e4654000000000000000000000000000000000000000000602082015261030c565b3480156105a957600080fd5b506105bd6105b8366004612b19565b611791565b6040516001600160a01b039091168152602001610319565b3480156105e157600080fd5b506103ab6105f0366004612eae565b61180b565b34801561060157600080fd5b50610615610610366004612b19565b61183b565b604080519384526001600160a01b03909216602084015290820152606001610319565b34801561064457600080fd5b5061037d610653366004612e93565b6118e2565b34801561066457600080fd5b506103ab61197c565b6103ab61067b366004612d02565b611990565b34801561068c57600080fd5b506106c061069b366004612eda565b600460205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b039093168352602083019190915201610319565b3480156106eb57600080fd5b506103ab6106fa366004612eae565b611c7d565b34801561070b57600080fd5b5061030c61071a366004612b92565b611cad565b34801561072b57600080fd5b506000546001600160a01b03166105bd565b34801561074957600080fd5b506103ab610758366004612ef5565b611d6c565b34801561076957600080fd5b5061037d60055481565b34801561077f57600080fd5b5061030c611daf565b34801561079457600080fd5b5061030c6107a3366004612b92565b611dbe565b3480156107b457600080fd5b506103ab6107c3366004612f31565b611e4f565b3480156107d457600080fd5b5061037d6107e3366004612b19565b611f3c565b3480156107f457600080fd5b506103ab610803366004612d9e565b611fc4565b34801561081457600080fd5b50610357610823366004612f9e565b611fde565b34801561083457600080fd5b506103ab610843366004612fe0565b612031565b34801561085457600080fd5b5061037d610863366004612b19565b60106020526000908152604090205481565b34801561088157600080fd5b50610357610890366004613011565b612108565b3480156108a157600080fd5b506103ab6108b036600461303b565b612299565b3480156108c157600080fd5b506108e86108d0366004612b19565b600f6020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001610319565b34801561090957600080fd5b5061037d60095481565b34801561091f57600080fd5b506104ad61092e366004612b19565b6122cc565b34801561093f57600080fd5b506103ab61094e366004612e93565b6123f5565b600081815260036020526040812080546060929061097357610973613077565b9060005260206000200180546109889061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546109b49061308d565b8015610a015780601f106109d657610100808354040283529160200191610a01565b820191906000526020600020905b8154815290600101906020018083116109e457829003601f168201915b50505050509050919050565b6060600a8054610a1c9061308d565b80601f0160208091040260200160405190810160405280929190818152602001828054610a489061308d565b8015610a955780601f10610a6a57610100808354040283529160200191610a95565b820191906000526020600020905b815481529060010190602001808311610a7857829003601f168201915b5050505050905090565b6000610aa9612485565b6000806000610ab78561183b565b91945092509050336001600160a01b03831614610b415760405162461bcd60e51b815260206004820152602260248201527f43616e206e6f7420776974686472617720736f6d656f6e6520656c736573206260448201527f696400000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600554610b4e90826130d7565b4211610b9c5760405162461bcd60e51b815260206004820152601260248201527f4269642069732074696d652d6c6f636b656400000000000000000000000000006044820152606401610b38565b6040516000906001600160a01b0384169085156108fc0290869084818181858888f160008b81526007602052604080822080546001600160a01b0319168155600181018390556002018290555191965094508a93507f223d0d5db4846341da7a5cc902b1a7c597e63b6c73b1c6267dc931d290c7affb9250610c50915060208082526018908201527f3078373736393734363836343732363137373432363936340000000000000000604082015260600190565b60405180910390a36001945050505050610c6a6001600255565b919050565b610c776124dc565b60008281526010602090815260409182902083905581518481529081018390527fa8b2c0f94a578b5a88c9c7d9242237165ea684a64cd32968c7f0dd6edd22dbe0910160405180910390a15050565b610cce6124dc565b6011546000908152600e6020908152604082208054600181018255908352912001610cf98282613138565b50601180546000908152600f6020526040808220805463ffffffff871663ffffffff19909116179055915491517f949a1ec513916b5e46ab2c5681369a4651bba074831b8da896b06a94e8d041b692610d5a92908252602082015260400190565b60405180910390a160118054906000610d72836131f8565b91905055505050565b33610d8e6000546001600160a01b031690565b6001600160a01b03161480610db257503360009081526001602052604090205460ff165b610dfe5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b38565b610e09838383612536565b505050565b6000610e1984611791565b6001600160a01b0316336001600160a01b031614610e9f5760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f6e6c79206f776e65722063616e206368616e6765204e4654206360448201527f6f6e74656e7400000000000000000000000000000000000000000000000000006064820152608401610b38565b600084815260036020526040812080548592859291610ec057610ec0613077565b906000526020600020019182610ed7929190613211565b5060408051858152600060208201527f0fe79316286f6a1e5cf32c3c4ff10c2a66b9cd66da3353db3789c4042ffb44ee910160405180910390a15060019392505050565b610f236124dc565b826011548110610f755760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000848152600e60205260409020805483919085908110610f9857610f98613077565b906000526020600020019081610fae9190613138565b5060408051858152602081018590527f949a1ec513916b5e46ab2c5681369a4651bba074831b8da896b06a94e8d041b691015b60405180910390a150505050565b60008160115481106110435760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b3360009081526001602052604090205460ff166110a25760405162461bcd60e51b815260206004820152601460248201527f4d696e74657220726f6c652072657175697265640000000000000000000000006044820152606401610b38565b6110aa6125b4565b6000818152601060209081526040808320879055958252600f8152858220548383526008909152949020805463ffffffff191663ffffffff909516949094179093555090919050565b8382826110fe612485565b3361110888611791565b6001600160a01b0316146111845760405162461bcd60e51b815260206004820152602c60248201527f53657474696e672061736b73206973206f6e6c7920616c6c6f77656420666f7260448201527f206f776e6564204e4654732100000000000000000000000000000000000000006064820152608401610b38565b6000878152600660205260409081902087905551869088907f403cbda48c4d379b57469bea093b63817816d893b467842ee46fd1c3c29c05f8906111cb90899089906132fb565b60405180910390a36111dd6001600255565b6000806111e98561183b565b509150915060006111f986611f3c565b11801561120e57508161120b86611f3c565b11155b1561130457600061121f83876125e6565b611229908461330f565b905061123486611791565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a38460405161127991815260200190565b60405180910390a4600061128c87611791565b6001600160a01b03166108fc839081150290604051600060405180830381858888f160008c815260076020908152604080832080546001600160a01b0319168155600181018490556002018390556006909152812055945061130193506112f892508a91506117919050565b8489898961266d565b50505b505050505050505050565b600e602052816000526040600020818154811061132b57600080fd5b906000526020600020016000915091505080546113479061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546113739061308d565b80156113c05780601f10611395576101008083540402835291602001916113c0565b820191906000526020600020905b8154815290600101906020018083116113a357829003601f168201915b505050505081565b60008181526010602052604090205460115460609190811061142c5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000838152601060209081526040808320548352600e825280832080548251818502810185019093528083529193909284015b8282101561150b57838290600052602060002001805461147e9061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546114aa9061308d565b80156114f75780601f106114cc576101008083540402835291602001916114f7565b820191906000526020600020905b8154815290600101906020018083116114da57829003601f168201915b50505050508152602001906001019061145f565b5050505091505b50919050565b606082601154811061156c5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000848152600e6020526040902080548490811061158c5761158c613077565b9060005260206000200180546115a19061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546115cd9061308d565b801561161a5780601f106115ef5761010080835404028352916020019161161a565b820191906000526020600020905b8154815290600101906020018083116115fd57829003601f168201915b505050505091505092915050565b604080516020808201835260608252600084815260038252838120845181548085028201870187529381018481529495909491938593859285015b8282101561170f5783829060005260206000200180546116829061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546116ae9061308d565b80156116fb5780601f106116d0576101008083540402835291602001916116fb565b820191906000526020600020905b8154815290600101906020018083116116de57829003601f168201915b505050505081526020019060010190611663565b505050915250909392505050565b600081815260106020526040812054601154811061177d5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b505060009081526010602052604090205490565b6000818152600c60205260408120546001600160a01b0316806118055760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604482015265103a37b5b2b760d11b6064820152608401610b38565b92915050565b6118136124dc565b600091825260086020526040909120805463ffffffff191663ffffffff909216919091179055565b6000818152600c6020526040812054819081906001600160a01b0316806118b35760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604482015265103a37b5b2b760d11b6064820152608401610b38565b5050506000918252506007602052604090206001810154815460029092015490926001600160a01b0390921691565b60006001600160a01b0382166119605760405162461bcd60e51b815260206004820152602760248201527f4e46543a2062616c616e636520717565727920666f7220746865207a65726f2060448201527f61646472657373000000000000000000000000000000000000000000000000006064820152608401610b38565b506001600160a01b03166000908152600d602052604090205490565b6119846124dc565b61198e60006128ba565b565b82828261199b612485565b6000806119a78861183b565b5091509150813411611a205760405162461bcd60e51b8152602060048201526024808201527f4e657720626964206d7573742065786365656420746865206578697374696e6760448201527f206f6e65000000000000000000000000000000000000000000000000000000006064820152608401610b38565b60008215611a51576040516000906001600160a01b0384169085156108fc0290869084818181858888f15050505050505b34611a5b8a611f3c565b108015611a7057506000611a6e8a611f3c565b115b15611a8557611a7e89611f3c565b9050611a88565b50345b600089815260076020526040908190206001810183905580546001600160a01b03191633178155426002909101555181908a907f223d0d5db4846341da7a5cc902b1a7c597e63b6c73b1c6267dc931d290c7affb90611aea908c908c906132fb565b60405180910390a334611afc8a611f3c565b108015611b1157506000611b0f8a611f3c565b115b15611b48576000336108fc611b258c611f3c565b611b2f903461330f565b6040518115909202916000818181858888f15050505050505b505050611b556001600255565b600080611b618561183b565b50915091506000611b7186611f3c565b118015611b86575081611b8386611f3c565b11155b15611c73576000611b9783876125e6565b611ba1908461330f565b9050611bac86611791565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a384604051611bf191815260200190565b60405180910390a46000611c0487611791565b6001600160a01b03166108fc839081150290604051600060405180830381858888f160008c815260076020908152604080832080546001600160a01b03191681556001810184905560020183905560069091528120559450611c7093506112f892508a91506117919050565b50505b5050505050505050565b611c856124dc565b6000918252600f6020526040909120805463ffffffff191663ffffffff909216919091179055565b600082815260036020526040902080546060919083908110611cd157611cd1613077565b906000526020600020018054611ce69061308d565b80601f0160208091040260200160405190810160405280929190818152602001828054611d129061308d565b8015611d5f5780601f10611d3457610100808354040283529160200191611d5f565b820191906000526020600020905b815481529060010190602001808311611d4257829003601f168201915b5050505050905092915050565b611d746124dc565b63ffffffff909216600090815260046020526040902080546001600160a01b039092166001600160a01b031990921691909117815560010155565b6060600b8054610a1c9061308d565b600082815260106020526040902054601154606091908110611e225760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000848152601060209081526040808320548352600e909152902080548490811061158c5761158c613077565b6000546001600160a01b031615611ea85760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a6564000000000000000000000000006044820152606401610b38565b611eb1336128ba565b611ebb6001600255565b62015180600555600a611ece8482613138565b50600b611edb8382613138565b506000805260046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec80546001600160a01b031916331790557f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ed555050565b6000818152600c60205260408120546001600160a01b031680611fb05760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604482015265103a37b5b2b760d11b6064820152608401610b38565b505060009081526006602052604090205490565b611fcc6124dc565b611fd88484848461290a565b50505050565b6000611fed338686868661266d565b7f3ba9136826ac751de05d770d8d34fa4440ada49a5fb0e9aa1678aece66dad976838360405161201e9291906132fb565b60405180910390a1506001949350505050565b6120396124dc565b81601154811061208b5760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000838152600e60209081526040822080546001810182559083529120016120b38382613138565b506000838152600e60205260408120546120cf9060019061330f565b60408051868152602081018390529192507f949a1ec513916b5e46ab2c5681369a4651bba074831b8da896b06a94e8d041b69101610fe1565b60003361211483611791565b6001600160a01b0316146121795760405162461bcd60e51b815260206004820152602660248201527f4e46543a207472616e73666572206f6620746f6b656e2074686174206973206e60448201526537ba1037bbb760d11b6064820152608401610b38565b6001600160a01b0383166121d95760405162461bcd60e51b815260206004820152602160248201527f4e46543a207472616e7366657220746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610b38565b600082815260066020526040812055336000908152600d6020526040812080546001929061220890849061330f565b90915550506001600160a01b0383166000908152600d602052604081208054600192906122369084906130d7565b90915550506000828152600c602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a450600192915050565b6122a16124dc565b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b60608160115481106123205760405162461bcd60e51b815260206004820152601c60248201527f5175657269656420636c61737320646f6573206e6f74206578697374000000006044820152606401610b38565b6000838152600e6020908152604080832080548251818502810185019093528083529193909284015b8282101561150b5783829060005260206000200180546123689061308d565b80601f01602080910402602001604051908101604052809291908181526020018280546123949061308d565b80156123e15780601f106123b6576101008083540402835291602001916123e1565b820191906000526020600020905b8154815290600101906020018083116123c457829003601f168201915b505050505081526020019060010190612349565b6123fd6124dc565b6001600160a01b0381166124795760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b38565b612482816128ba565b50565b60028054036124d65760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b38565b60028055565b6000546001600160a01b0316331461198e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b38565b60008381526003602090815260408220805460018101825590835291200161255f828483613211565b5060008381526003602052604081205461257b9060019061330f565b60408051868152602081018390529192507f0fe79316286f6a1e5cf32c3c4ff10c2a66b9cd66da3353db3789c4042ffb44ee9101610fe1565b60006125c23360095461297c565b506009805490819060006125d5836131f8565b91905055506125e38161298a565b90565b60008181526008602090815260408083205463ffffffff168084526004909252822080546001909101546001600160a01b039091169083620186a061262b8389613322565b6126359190613339565b90506000836001600160a01b03166108fc839081150290604051600060405180830381858888f150949b9a5050505050505050505050565b846001600160a01b031661268084611791565b6001600160a01b0316146126e55760405162461bcd60e51b815260206004820152602660248201527f4e46543a207472616e73666572206f6620746f6b656e2074686174206973206e60448201526537ba1037bbb760d11b6064820152608401610b38565b6001600160a01b0384166127455760405162461bcd60e51b815260206004820152602160248201527f4e46543a207472616e7366657220746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610b38565b6000838152600660205260408120556001600160a01b0385166000908152600d6020526040812080546001929061277d90849061330f565b90915550506001600160a01b0384166000908152600d602052604081208054600192906127ab9084906130d7565b90915550506000838152600c6020526040902080546001600160a01b0319166001600160a01b0386169081179091553b15612872576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a029061282d903390899088908890889060040161335b565b6020604051808303816000875af115801561284c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128709190613399565b505b82846001600160a01b0316866001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008481526003602052604090208054839183918690811061292e5761292e613077565b906000526020600020019182612945929190613211565b5060408051858152602081018590527f0fe79316286f6a1e5cf32c3c4ff10c2a66b9cd66da3353db3789c4042ffb44ee9101610fe1565b61298682826129d7565b5050565b600081815260036020526040812054900361248257600081815260036020908152604080832080546001810182559084528284208251938401909252928252909101906129869082613138565b6001600160a01b038216612a2d5760405162461bcd60e51b815260206004820152601d60248201527f4e46543a206d696e7420746f20746865207a65726f20616464726573730000006044820152606401610b38565b6000818152600c60205260409020546001600160a01b031615612a925760405162461bcd60e51b815260206004820152601960248201527f4e46543a20746f6b656e20616c7265616479206d696e746564000000000000006044820152606401610b38565b6001600160a01b0382166000908152600d60205260408120805460019290612abb9084906130d7565b90915550506000818152600c602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600060208284031215612b2b57600080fd5b5035919050565b6000815180845260005b81811015612b5857602081850181015186830182015201612b3c565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000612b8b6020830184612b32565b9392505050565b60008060408385031215612ba557600080fd5b50508035926020909101359150565b803563ffffffff81168114610c6a57600080fd5b634e487b7160e01b600052604160045260246000fd5b600082601f830112612bef57600080fd5b813567ffffffffffffffff80821115612c0a57612c0a612bc8565b604051601f8301601f19908116603f01168101908282118183101715612c3257612c32612bc8565b81604052838152866020858801011115612c4b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612c7e57600080fd5b612c8783612bb4565b9150602083013567ffffffffffffffff811115612ca357600080fd5b612caf85828601612bde565b9150509250929050565b60008083601f840112612ccb57600080fd5b50813567ffffffffffffffff811115612ce357600080fd5b602083019150836020828501011115612cfb57600080fd5b9250929050565b600080600060408486031215612d1757600080fd5b83359250602084013567ffffffffffffffff811115612d3557600080fd5b612d4186828701612cb9565b9497909650939450505050565b600080600060608486031215612d6357600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612d8857600080fd5b612d9486828701612bde565b9150509250925092565b60008060008060608587031215612db457600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612dd957600080fd5b612de587828801612cb9565b95989497509550505050565b600081518084526020808501808196508360051b8101915082860160005b85811015612e39578284038952612e27848351612b32565b98850198935090840190600101612e0f565b5091979650505050505050565b602081526000612b8b6020830184612df1565b6020815260008251602080840152612e746040840182612df1565b949350505050565b80356001600160a01b0381168114610c6a57600080fd5b600060208284031215612ea557600080fd5b612b8b82612e7c565b60008060408385031215612ec157600080fd5b82359150612ed160208401612bb4565b90509250929050565b600060208284031215612eec57600080fd5b612b8b82612bb4565b600080600060608486031215612f0a57600080fd5b612f1384612bb4565b9250612f2160208501612e7c565b9150604084013590509250925092565b600080600060608486031215612f4657600080fd5b833567ffffffffffffffff80821115612f5e57600080fd5b612f6a87838801612bde565b94506020860135915080821115612f8057600080fd5b50612f8d86828701612bde565b925050604084013590509250925092565b60008060008060608587031215612fb457600080fd5b612fbd85612e7c565b935060208501359250604085013567ffffffffffffffff811115612dd957600080fd5b60008060408385031215612ff357600080fd5b82359150602083013567ffffffffffffffff811115612ca357600080fd5b6000806040838503121561302457600080fd5b61302d83612e7c565b946020939093013593505050565b6000806040838503121561304e57600080fd5b61305783612e7c565b91506020830135801515811461306c57600080fd5b809150509250929050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806130a157607f821691505b60208210810361151257634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115611805576118056130c1565b601f821115610e0957600081815260208120601f850160051c810160208610156131115750805b601f850160051c820191505b818110156131305782815560010161311d565b505050505050565b815167ffffffffffffffff81111561315257613152612bc8565b61316681613160845461308d565b846130ea565b602080601f83116001811461319b57600084156131835750858301515b600019600386901b1c1916600185901b178555613130565b600085815260208120601f198616915b828110156131ca578886015182559484019460019091019084016131ab565b50858210156131e85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161320a5761320a6130c1565b5060010190565b67ffffffffffffffff83111561322957613229612bc8565b61323d83613237835461308d565b836130ea565b6000601f84116001811461327157600085156132595750838201355b600019600387901b1c1916600186901b1783556132cb565b600083815260209020601f19861690835b828110156132a25786850135825560209485019460019092019101613282565b50868210156132bf5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000612e746020830184866132d2565b81810381811115611805576118056130c1565b8082028115828204841417611805576118056130c1565b60008261335657634e487b7160e01b600052601260045260246000fd5b500490565b60006001600160a01b0380881683528087166020840152508460408301526080606083015261338e6080830184866132d2565b979650505050505050565b6000602082840312156133ab57600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612b8b57600080fdfea2646970667358221220b635039b0e2cc6145666b32639c81a57775ad7ed40f25b6d93eb73b0f790298764736f6c63430008130033