Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- ArtefinNFT
- Optimization enabled
- true
- Compiler version
- v0.8.12+commit.f00d7308
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:24:41.843280Z
Contract source code
// SPDX-License-Identifier: GPL
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
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;
constructor() {
_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() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
abstract contract Ownable is Context {
address internal _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
constructor() {
_transferOwnership(_msgSender());
}
*/
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
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 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");
_;
}
}
//https://github.com/willitscale/solidity-util/blob/000a42d4d7c1491cde4381c29d4b775fa7e99aac/lib/Strings.sol#L317-L336
/**
* Strings Library
*
* In summary this is a simple library of string functions which make simple
* string operations less tedious in solidity.
*
* Please be aware these functions can be quite gas heavy so use them only when
* necessary not to clog the blockchain with expensive transactions.
*
* @author James Lockhart <[email protected]>
*/
library Strings {
/**
* Concat (High gas cost)
*
* Appends two strings together and returns a new value
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string which will be the concatenated
* prefix
* @param _value The value to be the concatenated suffix
* @return string The resulting string from combinging the base and value
*/
function concat(string memory _base, string memory _value)
internal
pure
returns (string memory) {
bytes memory _baseBytes = bytes(_base);
bytes memory _valueBytes = bytes(_value);
assert(_valueBytes.length > 0);
string memory _tmpValue = new string(_baseBytes.length +
_valueBytes.length);
bytes memory _newValue = bytes(_tmpValue);
uint i;
uint j;
for (i = 0; i < _baseBytes.length; i++) {
_newValue[j++] = _baseBytes[i];
}
for (i = 0; i < _valueBytes.length; i++) {
_newValue[j++] = _valueBytes[i];
}
return string(_newValue);
}
/**
* Index Of
*
* Locates and returns the position of a character within a string
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string acting as the haystack to be
* searched
* @param _value The needle to search for, at present this is currently
* limited to one character
* @return int The position of the needle starting from 0 and returning -1
* in the case of no matches found
*/
function indexOf(string memory _base, string memory _value)
internal
pure
returns (int) {
return _indexOf(_base, _value, 0);
}
/**
* Index Of
*
* Locates and returns the position of a character within a string starting
* from a defined offset
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string acting as the haystack to be
* searched
* @param _value The needle to search for, at present this is currently
* limited to one character
* @param _offset The starting point to start searching from which can start
* from 0, but must not exceed the length of the string
* @return int The position of the needle starting from 0 and returning -1
* in the case of no matches found
*/
function _indexOf(string memory _base, string memory _value, uint _offset)
internal
pure
returns (int) {
bytes memory _baseBytes = bytes(_base);
bytes memory _valueBytes = bytes(_value);
assert(_valueBytes.length == 1);
for (uint i = _offset; i < _baseBytes.length; i++) {
if (_baseBytes[i] == _valueBytes[0]) {
return int(i);
}
}
return -1;
}
/**
* Length
*
* Returns the length of the specified string
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string to be measured
* @return uint The length of the passed string
*/
function length(string memory _base)
internal
pure
returns (uint) {
bytes memory _baseBytes = bytes(_base);
return _baseBytes.length;
}
/**
* Sub String
*
* Extracts the beginning part of a string based on the desired length
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string that will be used for
* extracting the sub string from
* @param _length The length of the sub string to be extracted from the base
* @return string The extracted sub string
*/
function substring(string memory _base, int _length)
internal
pure
returns (string memory) {
return _substring(_base, _length, 0);
}
/**
* Sub String
*
* Extracts the part of a string based on the desired length and offset. The
* offset and length must not exceed the lenth of the base string.
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string that will be used for
* extracting the sub string from
* @param _length The length of the sub string to be extracted from the base
* @param _offset The starting point to extract the sub string from
* @return string The extracted sub string
*/
function _substring(string memory _base, int _length, int _offset)
internal
pure
returns (string memory) {
bytes memory _baseBytes = bytes(_base);
assert(uint(_offset + _length) <= _baseBytes.length);
string memory _tmp = new string(uint(_length));
bytes memory _tmpBytes = bytes(_tmp);
uint j = 0;
for (uint i = uint(_offset); i < uint(_offset + _length); i++) {
_tmpBytes[j++] = _baseBytes[i];
}
return string(_tmpBytes);
}
function split(string memory _base, string memory _value)
internal
pure
returns (string[] memory splitArr) {
bytes memory _baseBytes = bytes(_base);
uint _offset = 0;
uint _splitsCount = 1;
while (_offset < _baseBytes.length - 1) {
int _limit = _indexOf(_base, _value, _offset);
if (_limit == -1)
break;
else {
_splitsCount++;
_offset = uint(_limit) + 1;
}
}
splitArr = new string[](_splitsCount);
_offset = 0;
_splitsCount = 0;
while (_offset < _baseBytes.length - 1) {
int _limit = _indexOf(_base, _value, _offset);
if (_limit == - 1) {
_limit = int(_baseBytes.length);
}
string memory _tmp = new string(uint(_limit) - _offset);
bytes memory _tmpBytes = bytes(_tmp);
uint j = 0;
for (uint i = _offset; i < uint(_limit); i++) {
_tmpBytes[j++] = _baseBytes[i];
}
_offset = uint(_limit) + 1;
splitArr[_splitsCount++] = string(_tmpBytes);
}
return splitArr;
}
/**
* Compare To
*
* Compares the characters of two strings, to ensure that they have an
* identical footprint
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string base to compare against
* @param _value The string the base is being compared to
* @return bool Simply notates if the two string have an equivalent
*/
function compareTo(string memory _base, string memory _value)
internal
pure
returns (bool) {
bytes memory _baseBytes = bytes(_base);
bytes memory _valueBytes = bytes(_value);
if (_baseBytes.length != _valueBytes.length) {
return false;
}
for (uint i = 0; i < _baseBytes.length; i++) {
if (_baseBytes[i] != _valueBytes[i]) {
return false;
}
}
return true;
}
/**
* Compare To Ignore Case (High gas cost)
*
* Compares the characters of two strings, converting them to the same case
* where applicable to alphabetic characters to distinguish if the values
* match.
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string base to compare against
* @param _value The string the base is being compared to
* @return bool Simply notates if the two string have an equivalent value
* discarding case
*/
function compareToIgnoreCase(string memory _base, string memory _value)
internal
pure
returns (bool) {
bytes memory _baseBytes = bytes(_base);
bytes memory _valueBytes = bytes(_value);
if (_baseBytes.length != _valueBytes.length) {
return false;
}
for (uint i = 0; i < _baseBytes.length; i++) {
if (_baseBytes[i] != _valueBytes[i] &&
_upper(_baseBytes[i]) != _upper(_valueBytes[i])) {
return false;
}
}
return true;
}
/**
* Upper
*
* Converts all the values of a string to their corresponding upper case
* value.
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string base to convert to upper case
* @return string
*/
function upper(string memory _base)
internal
pure
returns (string memory) {
bytes memory _baseBytes = bytes(_base);
for (uint i = 0; i < _baseBytes.length; i++) {
_baseBytes[i] = _upper(_baseBytes[i]);
}
return string(_baseBytes);
}
/**
* Lower
*
* Converts all the values of a string to their corresponding lower case
* value.
*
* @param _base When being used for a data type this is the extended object
* otherwise this is the string base to convert to lower case
* @return string
*/
function lower(string memory _base)
internal
pure
returns (string memory) {
bytes memory _baseBytes = bytes(_base);
for (uint i = 0; i < _baseBytes.length; i++) {
_baseBytes[i] = _lower(_baseBytes[i]);
}
return string(_baseBytes);
}
/**
* Upper
*
* Convert an alphabetic character to upper case and return the original
* value when not alphabetic
*
* @param _b1 The byte to be converted to upper case
* @return bytes1 The converted value if the passed value was alphabetic
* and in a lower case otherwise returns the original value
*/
function _upper(bytes1 _b1)
private
pure
returns (bytes1) {
if (_b1 >= 0x61 && _b1 <= 0x7A) {
return bytes1(uint8(_b1) - 32);
}
return _b1;
}
/**
* Lower
*
* Convert an alphabetic character to lower case and return the original
* value when not alphabetic
*
* @param _b1 The byte to be converted to lower case
* @return bytes1 The converted value if the passed value was alphabetic
* and in a upper case otherwise returns the original value
*/
function _lower(bytes1 _b1)
private
pure
returns (bytes1) {
if (_b1 >= 0x41 && _b1 <= 0x5A) {
return bytes1(uint8(_b1) + 32);
}
return _b1;
}
}
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing a contract.
*
* > It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
}
interface ICallistoNFT {
event NewBid (uint256 indexed tokenID, uint256 indexed bidAmount, bytes bidData);
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 Strings for string;
using Address for address;
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);
payable(ownerOf(_tokenId)).transfer(_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;
return true;
}
function _addPropertyWithContent(uint256 _tokenId, string calldata _content) internal
{
// Check permission criteria
_tokenProperties[_tokenId].properties.push(_content);
}
function _modifyProperty(uint256 _tokenId, uint256 _propertyId, string calldata _content) internal
{
_tokenProperties[_tokenId].properties[_propertyId] = _content;
}
function _appendProperty(uint256 _tokenId, uint256 _propertyId, string calldata _content) internal
{
_tokenProperties[_tokenId].properties[_propertyId] = _tokenProperties[_tokenId].properties[_propertyId].concat(_content);
}
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;
}
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)
{
_previousBidder.transfer(_previousBid);
}
// Refund overpaid amount.
if (priceOf(_tokenId) < msg.value)
{
_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.
// WARHNING: Creates possibility for reentrancy.
if (priceOf(_tokenId) < msg.value)
{
payable(msg.sender).transfer(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");
_bidder.transfer(_bid);
delete _bids[_tokenId];
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;
payable(_feeReceiver).transfer(_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 setClassForTokenID(uint256 _tokenID, uint256 _tokenClass) external;
function addNewTokenClass(uint32 _feeLevel, string memory _property) external;
function addTokenClassProperties(uint256 _propertiesCount, uint256 classId) external;
function modifyClassProperty(uint256 _classID, uint256 _propertyID, string memory _content) external;
function getClassProperty(uint256 _classID, uint256 _propertyID) external view returns (string memory);
function addClassProperty(uint256 _classID) external;
function getClassProperties(uint256 _classID) external view returns (string[] memory);
function getClassForTokenID(uint256 _tokenID) external view returns (uint256);
function getClassPropertiesForTokenID(uint256 _tokenID) external view returns (string[] memory);
function getClassPropertyForTokenID(uint256 _tokenID, uint256 _propertyID) external view returns (string memory);
function mintWithClass(uint256 classId) external returns (uint256 _newTokenID);
function appendClassProperty(uint256 _classID, uint256 _propertyID, string memory _content) external;
}
abstract contract ClassifiedNFT is MinterRole, ExtendedNFT, IClassifiedNFT {
using Strings for string;
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 setClassForTokenID(uint256 _tokenID, uint256 _tokenClass) public onlyOwner override
{
token_classes[_tokenID] = _tokenClass;
}
function addNewTokenClass(uint32 _feeLevel, string memory _property) public onlyOwner override
{
class_properties[nextClassIndex].push(_property);
class_feeLevel[nextClassIndex] = _feeLevel; // Configures who will receive fees from this class of NFTs
// Zero sets fees to default address and percentage.
nextClassIndex++;
}
function addTokenClassProperties(uint256 _propertiesCount, uint256 classId) public onlyOwner override
{
for (uint i = 0; i < _propertiesCount; i++)
{
class_properties[classId].push("");
}
}
function modifyClassProperty(uint256 _classID, uint256 _propertyID, string memory _content) public onlyOwner onlyExistingClasses(_classID) override
{
class_properties[_classID][_propertyID] = _content;
}
function getClassProperty(uint256 _classID, uint256 _propertyID) public view onlyExistingClasses(_classID) override returns (string memory)
{
return class_properties[_classID][_propertyID];
}
function addClassProperty(uint256 _classID) public onlyOwner onlyExistingClasses(_classID) override
{
class_properties[_classID].push("");
}
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 getClassPropertiesForTokenID(uint256 _tokenID) public view onlyExistingClasses(token_classes[_tokenID]) override returns (string[] memory)
{
return class_properties[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 mintWithClass(uint256 classId) public onlyExistingClasses(classId) onlyMinter override returns (uint256 _newTokenID)
{
//_mint(to, tokenId);
_newTokenID = mint();
token_classes[_newTokenID] = classId;
_tokenFeeLevels[_newTokenID] = class_feeLevel[classId];
}
function appendClassProperty(uint256 _classID, uint256 _propertyID, string memory _content) public onlyOwner onlyExistingClasses(_classID) override
{
class_properties[_classID][_propertyID] = class_properties[_classID][_propertyID].concat(_content);
}
}
contract ArtefinNFT is ExtendedNFT, ClassifiedNFT {
function initialize(string memory name_, string memory symbol_, uint256 _defaultFee) external {
require(_owner == address(0), "Already initialized");
_owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
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 addPropertyWithContentForMinter(uint256 _tokenId, string calldata _content) public onlyMinter
{
_addPropertyWithContent( _tokenId, _content);
}
*/
function modifyProperty(uint256 _tokenId, uint256 _propertyId, string calldata _content) public onlyOwner
{
_modifyProperty(_tokenId, _propertyId, _content);
}
function appendProperty(uint256 _tokenId, uint256 _propertyId, string calldata _content) public onlyOwner
{
_appendProperty(_tokenId, _propertyId, _content);
}
function migrationMint (address to, uint256 _tokenId, uint256 _classID, string calldata _serialNumber) public onlyMinter {
require(to != address(0), "NFT: mint to the zero address");
require(!_exists(_tokenId), "NFT: token already minted");
_beforeTokenTransfer(address(0), to, _tokenId);
_configureNFT(_tokenId);
token_classes[_tokenId] = _classID;
_tokenFeeLevels[_tokenId] = class_feeLevel[_classID];
_addPropertyWithContent(_tokenId, _serialNumber);
_balances[to] += 1;
_owners[_tokenId] = to;
emit Transfer(address(0), to, _tokenId);
}
function setNextMintID (uint256 _next_mint_id) public onlyOwner {
require(_next_mint_id > next_mint_id, "next_mint_id must be higher than last token ID");
next_mint_id = _next_mint_id;
}
}
contract ActivatedByOwner is Ownable {
bool public active = true;
function setActive(bool _active) public onlyOwner
{
active = _active;
}
modifier onlyActive
{
require(active, "This contract is deactivated by owner");
_;
}
}
contract NFTMulticlassLinearAuction is ActivatedByOwner {
event AuctionCreated(uint256 indexed tokenClassAuctionID, uint256 timestamp);
event TokenSold(uint256 indexed tokenID, uint256 indexed tokenClassID, address indexed buyer);
event NFTContractSet(address indexed newNFTContract, address indexed oldNFTContract);
event RevenueWithdrawal(uint256 amount);
address public nft_contract;
struct NFTAuctionClass
{
uint256 max_supply;
uint256 amount_sold;
uint256 start_timestamp;
uint256 duration;
uint256 priceInWei;
string[] configuratin_properties;
}
mapping (uint256 => NFTAuctionClass) public auctions; // Mapping from classID (at NFT contract) to set of variables
// defining the auction for this token class.
address payable public revenue = payable(0x01000B5fE61411C466b70631d7fF070187179Bbf); // This address has the rights to withdraw funds from the auction.
constructor()
{
_owner = msg.sender;
}
function createNFTAuction(
uint256 _classID,
uint256 _max_supply,
uint256 _start_timestamp,
uint256 _duration,
uint256 _priceInWEI,
uint256 _already_sold
) public onlyOwner
{
auctions[_classID].max_supply = _max_supply;
auctions[_classID].amount_sold = _already_sold;
auctions[_classID].start_timestamp = _start_timestamp;
auctions[_classID].duration = _duration;
auctions[_classID].priceInWei = _priceInWEI;
emit AuctionCreated(_classID, block.timestamp);
}
function setRevenueAddress(address payable _revenue_address) public onlyOwner {
revenue = _revenue_address;
}
function setNFTContract(address _nftContract) public onlyOwner
{
emit NFTContractSet(_nftContract, nft_contract);
nft_contract = _nftContract;
}
function buyNFT(uint256 _classID) public payable onlyActive
{
// WARNING!
// This function does not refund overpaid amount at the moment.
// TODO
require(msg.value >= auctions[_classID].priceInWei, "Insufficient funds");
require(auctions[_classID].amount_sold < auctions[_classID].max_supply, "This auction has already sold all allocated NFTs");
require(block.timestamp < auctions[_classID].start_timestamp + auctions[_classID].duration, "This auction already expired");
require(block.timestamp > auctions[_classID].start_timestamp, "This auction is not yet started");
require(auctions[_classID].priceInWei != 0, "Min price is not configured by the owner");
uint256 _mintedId = ClassifiedNFT(nft_contract).mintWithClass(_classID);
auctions[_classID].amount_sold++;
configureNFT(_mintedId, _classID);
ClassifiedNFT(nft_contract).transfer(msg.sender, _mintedId, "");
emit TokenSold(_mintedId, _classID, msg.sender);
}
function configureNFT(uint256 _tokenId, uint256 _classId) internal
{
//Add Serial Number to the created Token
uint256 tokenSerialNumber = auctions[_classId].amount_sold;
ArtefinNFT(nft_contract).addPropertyWithContent(_tokenId, toString(tokenSerialNumber));
}
function withdrawRevenue() public onlyOwner
{
require(msg.sender == revenue, "This action requires revenue permission");
emit RevenueWithdrawal(address(this).balance);
revenue.transfer(address(this).balance);
}
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol#L15-L35
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
contract NFTMulticlassBiddableAuction is ActivatedByOwner {
event AuctionCreated(uint256 indexed tokenClassAuctionID, uint256 timestamp);
//event TokenSold(uint256 indexed tokenID, uint256 indexed tokenClassID, address indexed buyer);
event NFTContractSet(address indexed newNFTContract, address indexed oldNFTContract);
event RevenueWithdrawal(uint256 amount);
event RoundEnd(uint256 indexed tokenClassAuctionID, address indexed winner, uint256 indexed acquiredTokenID);
event NewRound(uint256 indexed tokenClassAuctionID, uint256 indexed startTimestamp, uint256 indexed endTimestamp);
address public nft_contract;
struct NFTBiddableAuctionClass
{
uint256 max_supply;
uint256 amount_sold;
uint256 start_timestamp;
uint256 duration;
uint256 min_priceInWei;
uint256 highest_bid;
address winner;
string[] configuratin_properties;
}
struct NFTBidClass
{
uint256 classID;
address owner;
uint256 bid_amount;
uint256 bid_timestamp;
}
mapping (uint256 => NFTBidClass) public bids; // Mapping all bids
uint256 public nextBidIndex = 0; //Bids index
mapping (uint256 => NFTBiddableAuctionClass) public auctions; // Mapping from classID (at NFT contract) to set of variables
// defining the auction for this token class.
uint256 public revenue_amount; // total amount of revenue
address payable public revenue = payable(0x01000B5fE61411C466b70631d7fF070187179Bbf); // This address has the rights to withdraw funds from the auction.
constructor()
{
_owner = msg.sender;
}
function createNFTAuction(
uint256 _classID,
uint256 _max_supply,
uint256 _start_timestamp,
uint256 _duration,
uint256 _minPriceInWEI,
uint256 _already_sold
) public onlyOwner
{
auctions[_classID].max_supply = _max_supply;
auctions[_classID].amount_sold = _already_sold;
auctions[_classID].start_timestamp = _start_timestamp;
auctions[_classID].duration = _duration;
auctions[_classID].min_priceInWei = _minPriceInWEI;
auctions[_classID].winner = owner();
emit AuctionCreated(_classID, block.timestamp);
}
function setRevenueAddress(address payable _revenue_address) public onlyOwner {
revenue = _revenue_address;
}
function setNFTContract(address _nftContract) public onlyOwner
{
emit NFTContractSet(nft_contract, _nftContract);
nft_contract = _nftContract;
}
function bidOnNFT(uint256 _classID) public payable onlyActive
{
uint256 _bid = msg.value;
require(_bid >= auctions[_classID].min_priceInWei, "Min price criteria is not met");
require(auctions[_classID].start_timestamp < block.timestamp, "Auction did not start yet");
if(auctions[_classID].start_timestamp + auctions[_classID].duration < block.timestamp)
{
endRound(_classID);
payable(msg.sender).transfer(_bid - auctions[_classID].min_priceInWei);
_bid = auctions[_classID].min_priceInWei;
}
require(auctions[_classID].max_supply > auctions[_classID].amount_sold, "All NFTs of this artwork are already sold");
require(
_bid >= auctions[_classID].highest_bid + auctions[_classID].highest_bid/20 &&
_bid >= auctions[_classID].highest_bid + 1e18,
"Does not outbid current winner by 5%"
);
require(auctions[_classID].min_priceInWei != 0, "Min price is not configured by the owner");
payable(auctions[_classID].winner).transfer(auctions[_classID].highest_bid);
auctions[_classID].winner = msg.sender;
auctions[_classID].highest_bid = _bid;
bids[nextBidIndex].classID = _classID;
bids[nextBidIndex].owner = msg.sender;
bids[nextBidIndex].bid_amount = _bid;
bids[nextBidIndex].bid_timestamp = block.timestamp;
nextBidIndex++;
}
function resetRound(uint256 _classID) internal
{
auctions[_classID].winner = owner();
auctions[_classID].highest_bid = 0;
auctions[_classID].start_timestamp = block.timestamp + 600;
emit NewRound(_classID, auctions[_classID].start_timestamp, auctions[_classID].start_timestamp + auctions[_classID].duration);
}
function endRound(uint256 _classID) public
{
require(block.timestamp > auctions[_classID].start_timestamp + auctions[_classID].duration, "Auction is still in progress");
require(auctions[_classID].max_supply > auctions[_classID].amount_sold, "All NFTs of this artwork are already sold");
auctions[_classID].amount_sold++;
uint256 _mintedId = ClassifiedNFT(nft_contract).mintWithClass(_classID);
configureNFT(_mintedId, _classID);
ClassifiedNFT(nft_contract).transfer(auctions[_classID].winner, _mintedId, "");
emit RoundEnd(_classID, auctions[_classID].winner, _mintedId);
revenue_amount += auctions[_classID].highest_bid;
if(auctions[_classID].amount_sold != auctions[_classID].max_supply)
{
resetRound(_classID);
}
}
function configureNFT(uint256 _tokenId, uint256 _classId) internal
{
//Add Serial Number to the created Token
uint256 tokenSerialNumber = auctions[_classId].amount_sold;
ArtefinNFT(nft_contract).addPropertyWithContent(_tokenId, toString(tokenSerialNumber));
}
function withdrawRevenue() public onlyOwner
{
require(msg.sender == revenue, "This action requires revenue permission");
uint256 toPay = revenue_amount;
revenue_amount = 0;
revenue.transfer(toPay);
emit RevenueWithdrawal(toPay);
}
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol#L15-L35
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
Contract ABI
[{"type":"event","name":"NewBid","inputs":[{"type":"uint256","name":"tokenID","internalType":"uint256","indexed":true},{"type":"uint256","name":"bidAmount","internalType":"uint256","indexed":true},{"type":"bytes","name":"bidData","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":"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":"function","stateMutability":"nonpayable","outputs":[],"name":"addNewTokenClass","inputs":[{"type":"uint32","name":"_feeLevel","internalType":"uint32"},{"type":"string","name":"_property","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":"nonpayable","outputs":[],"name":"addTokenClassProperties","inputs":[{"type":"uint256","name":"_propertiesCount","internalType":"uint256"},{"type":"uint256","name":"classId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"appendClassProperty","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":"appendProperty","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":"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":[],"name":"migrationMint","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"uint256","name":"_classID","internalType":"uint256"},{"type":"string","name":"_serialNumber","internalType":"string"}]},{"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":"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":"setNextMintID","inputs":[{"type":"uint256","name":"_next_mint_id","internalType":"uint256"}]},{"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
0x608060405262015180600555600060115534801561001c57600080fd5b506001600255613603806100316000396000f3fe6080604052600436106102935760003560e01c806373baa6511161015a578063bb053717116100c1578063d75d1e661161007a578063d75d1e661461089a578063e29fb036146108e2578063e6470059146108f8578063eed9940814610918578063f2fde38b14610938578063f44079861461095857600080fd5b8063bb053717146107cd578063be45fd62146107ed578063be6710581461080d578063c1940f1b1461082d578063c98e0c3c1461085a578063cb177b1e1461087a57600080fd5b80638e39e18c116101135780638e39e18c14610722578063911006951461074257806395d89b41146107585780639de4792e1461076d578063b119490e1461078d578063b9186d7d146107ad57600080fd5b806373baa6511461063257806374c29ce31461064557806378317f3f146106a45780637ab56e52146106c457806380483a6a146106e45780638da5cb5b1461070457600080fd5b80633e0bb783116101fe578063543dc7fa116101b7578063543dc7fa146105235780635a3b7e42146105435780636352211e14610577578063648fbe40146105af578063649ccc14146105cf57806370a082311461061257600080fd5b80633e0bb783146104395780634774d93f146104595780634bb2ddd4146104795780634c1720a4146104a65780634edea111146104c6578063510910bb146104f357600080fd5b8063290e008c11610250578063290e008c146103795780632a6d3f44146103995780633054d9cb146103b95780633add5fa1146103d95780633c65b3eb146103f95780633d8073f11461041957600080fd5b806302ff368a1461029857806306fdde03146102ce5780630eaaf4c8146102e35780631d734c8f146103135780631f38e6541461033757806325498c7514610359575b600080fd5b3480156102a457600080fd5b506102b86102b3366004612cf4565b610978565b6040516102c59190612d5a565b60405180910390f35b3480156102da57600080fd5b506102b8610a32565b3480156102ef57600080fd5b506103036102fe366004612cf4565b610ac4565b60405190151581526020016102c5565b34801561031f57600080fd5b5061032960115481565b6040519081526020016102c5565b34801561034357600080fd5b50610357610352366004612d74565b610c2a565b005b34801561036557600080fd5b50610357610374366004612e52565b610c66565b34801561038557600080fd5b50610357610394366004612ee9565b610d01565b3480156103a557600080fd5b506103036103b4366004612ee9565b610d64565b3480156103c557600080fd5b506103576103d4366004612f35565b610e21565b3480156103e557600080fd5b506103576103f4366004612f85565b610eb4565b34801561040557600080fd5b50610329610414366004612cf4565b610ef0565b34801561042557600080fd5b50610357610434366004612f85565b610fbb565b34801561044557600080fd5b506102b8610454366004612d74565b6111a9565b34801561046557600080fd5b50610357610474366004612f35565b611262565b34801561048557600080fd5b50610499610494366004612cf4565b611395565b6040516102c5919061302d565b3480156104b257600080fd5b506102b86104c1366004612d74565b6114b5565b3480156104d257600080fd5b506104e66104e1366004612cf4565b611595565b6040516102c59190613040565b3480156104ff57600080fd5b5061030361050e36600461307a565b60016020526000908152604090205460ff1681565b34801561052f57600080fd5b5061032961053e366004612cf4565b61168a565b34801561054f57600080fd5b5060408051808201909152600b81526a10d85b1b1a5cdd1bd3919560aa1b60208201526102b8565b34801561058357600080fd5b50610597610592366004612cf4565b6116ce565b6040516001600160a01b0390911681526020016102c5565b3480156105bb57600080fd5b506103576105ca366004613095565b611709565b3480156105db57600080fd5b506105ef6105ea366004612cf4565b61175b565b604080519384526001600160a01b039092166020840152908201526060016102c5565b34801561061e57600080fd5b5061032961062d36600461307a565b6117c3565b610357610640366004612ee9565b611847565b34801561065157600080fd5b506106856106603660046130c1565b600460205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b0390931683526020830191909152016102c5565b3480156106b057600080fd5b506103576106bf366004613095565b611b32565b3480156106d057600080fd5b506102b86106df366004612d74565b611b84565b3480156106f057600080fd5b506103576106ff366004612cf4565b611c43565b34801561071057600080fd5b506000546001600160a01b0316610597565b34801561072e57600080fd5b5061035761073d3660046130dc565b611cc7565b34801561074e57600080fd5b5061032960055481565b34801561076457600080fd5b506102b8611d2c565b34801561077957600080fd5b506102b8610788366004612d74565b611d3b565b34801561079957600080fd5b506103576107a8366004613118565b611d9c565b3480156107b957600080fd5b506103296107c8366004612cf4565b611eb9565b3480156107d957600080fd5b506103576107e8366004612f85565b611f02565b3480156107f957600080fd5b50610303610808366004613185565b611f38565b34801561081957600080fd5b50610357610828366004612d74565b611f8b565b34801561083957600080fd5b50610329610848366004612cf4565b60106020526000908152604090205481565b34801561086657600080fd5b506103036108753660046131c7565b61200b565b34801561088657600080fd5b506103576108953660046131f1565b612111565b3480156108a657600080fd5b506108cd6108b5366004612cf4565b600f6020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016102c5565b3480156108ee57600080fd5b5061032960095481565b34801561090457600080fd5b50610499610913366004612cf4565b612166565b34801561092457600080fd5b5061035761093336600461322d565b61225f565b34801561094457600080fd5b5061035761095336600461307a565b612439565b34801561096457600080fd5b50610357610973366004612cf4565b6124d4565b600081815260036020526040812080546060929061099857610998613295565b9060005260206000200180546109ad906132ab565b80601f01602080910402602001604051908101604052809291908181526020018280546109d9906132ab565b8015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b50505050509050919050565b6060600a8054610a41906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6d906132ab565b8015610aba5780601f10610a8f57610100808354040283529160200191610aba565b820191906000526020600020905b815481529060010190602001808311610a9d57829003601f168201915b5050505050905090565b6000600280541415610af15760405162461bcd60e51b8152600401610ae8906132e0565b60405180910390fd5b6002805560008080610b028561175b565b91945092509050336001600160a01b03831614610b6c5760405162461bcd60e51b815260206004820152602260248201527f43616e206e6f7420776974686472617720736f6d656f6e6520656c73657320626044820152611a5960f21b6064820152608401610ae8565b600554610b79908261332d565b4211610bbc5760405162461bcd60e51b8152602060048201526012602482015271109a59081a5cc81d1a5b594b5b1bd8dad95960721b6044820152606401610ae8565b6040516001600160a01b0383169084156108fc029085906000818181858888f19350505050158015610bf2573d6000803e3d6000fd5b5050506000928352505060076020526040812080546001600160a01b0319168155600180820183905560029182019290925581905590565b6000546001600160a01b03163314610c545760405162461bcd60e51b8152600401610ae890613345565b60009182526010602052604090912055565b6000546001600160a01b03163314610c905760405162461bcd60e51b8152600401610ae890613345565b6011546000908152600e6020908152604082208054600181018255908352918190208351610cc5939190910191840190612be7565b50601180546000908152600f60205260408120805463ffffffff191663ffffffff861617905581549190610cf88361337a565b91905055505050565b33610d146000546001600160a01b031690565b6001600160a01b03161480610d3857503360009081526001602052604090205460ff165b610d545760405162461bcd60e51b8152600401610ae890613345565b610d5f83838361256b565b505050565b6000610d6f846116ce565b6001600160a01b0316336001600160a01b031614610dde5760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f6e6c79206f776e65722063616e206368616e6765204e465420636044820152651bdb9d195b9d60d21b6064820152608401610ae8565b600084815260036020526040812080548592859291610dff57610dff613295565b906000526020600020019190610e16929190612c6b565b506001949350505050565b6000546001600160a01b03163314610e4b5760405162461bcd60e51b8152600401610ae890613345565b826011548110610e6d5760405162461bcd60e51b8152600401610ae890613395565b6000848152600e60205260409020805483919085908110610e9057610e90613295565b906000526020600020019080519060200190610ead929190612be7565b5050505050565b6000546001600160a01b03163314610ede5760405162461bcd60e51b8152600401610ae890613345565b610eea84848484612594565b50505050565b6000816011548110610f145760405162461bcd60e51b8152600401610ae890613395565b3360009081526001602052604090205460ff16610f6a5760405162461bcd60e51b8152602060048201526014602482015273135a5b9d195c881c9bdb19481c995c5d5a5c995960621b6044820152606401610ae8565b610f7261260d565b6000818152601060209081526040808320879055958252600f8152858220548383526008909152949020805463ffffffff191663ffffffff909516949094179093555090919050565b838282600280541415610fe05760405162461bcd60e51b8152600401610ae8906132e0565b6002805533610fee886116ce565b6001600160a01b0316146110595760405162461bcd60e51b815260206004820152602c60248201527f53657474696e672061736b73206973206f6e6c7920616c6c6f77656420666f7260448201526b206f776e6564204e4654732160a01b6064820152608401610ae8565b60008781526006602052604081208790556001600255806110798561175b565b5091509150600061108986611eb9565b11801561109e57508161109b86611eb9565b11155b1561119e5760006110af838761263f565b6110b990846133cc565b90506110c4866116ce565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a38460405161110991815260200190565b60405180910390a461111a866116ce565b6001600160a01b03166108fc829081150290604051600060405180830381858888f19350505050158015611152573d6000803e3d6000fd5b50600086815260076020908152604080832080546001600160a01b031916815560018101849055600201839055600690915281205561119c611193876116ce565b838888886126d2565b505b505050505050505050565b600e60205281600052604060002081815481106111c557600080fd5b906000526020600020016000915091505080546111e1906132ab565b80601f016020809104026020016040519081016040528092919081815260200182805461120d906132ab565b801561125a5780601f1061122f5761010080835404028352916020019161125a565b820191906000526020600020905b81548152906001019060200180831161123d57829003601f168201915b505050505081565b6000546001600160a01b0316331461128c5760405162461bcd60e51b8152600401610ae890613345565b8260115481106112ae5760405162461bcd60e51b8152600401610ae890613395565b6000848152600e602052604090208054611375918491869081106112d4576112d4613295565b9060005260206000200180546112e9906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054611315906132ab565b80156113625780601f1061133757610100808354040283529160200191611362565b820191906000526020600020905b81548152906001019060200180831161134557829003601f168201915b505050505061287b90919063ffffffff16565b6000858152600e60205260409020805485908110610e9057610e90613295565b6000818152601060205260409020546011546060919081106113c95760405162461bcd60e51b8152600401610ae890613395565b6000838152601060209081526040808320548352600e825280832080548251818502810185019093528083529193909284015b828210156114a857838290600052602060002001805461141b906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054611447906132ab565b80156114945780601f1061146957610100808354040283529160200191611494565b820191906000526020600020905b81548152906001019060200180831161147757829003601f168201915b5050505050815260200190600101906113fc565b5050505091505b50919050565b60608260115481106114d95760405162461bcd60e51b8152600401610ae890613395565b6000848152600e602052604090208054849081106114f9576114f9613295565b90600052602060002001805461150e906132ab565b80601f016020809104026020016040519081016040528092919081815260200182805461153a906132ab565b80156115875780601f1061155c57610100808354040283529160200191611587565b820191906000526020600020905b81548152906001019060200180831161156a57829003601f168201915b505050505091505092915050565b604080516020808201835260608252600084815260038252838120845181548085028201870187529381018481529495909491938593859285015b8282101561167c5783829060005260206000200180546115ef906132ab565b80601f016020809104026020016040519081016040528092919081815260200182805461161b906132ab565b80156116685780601f1061163d57610100808354040283529160200191611668565b820191906000526020600020905b81548152906001019060200180831161164b57829003601f168201915b5050505050815260200190600101906115d0565b505050915250909392505050565b60008181526010602052604081205460115481106116ba5760405162461bcd60e51b8152600401610ae890613395565b505060009081526010602052604090205490565b6000818152600c60205260408120546001600160a01b0316806117035760405162461bcd60e51b8152600401610ae8906133e3565b92915050565b6000546001600160a01b031633146117335760405162461bcd60e51b8152600401610ae890613345565b600091825260086020526040909120805463ffffffff191663ffffffff909216919091179055565b6000818152600c6020526040812054819081906001600160a01b0316806117945760405162461bcd60e51b8152600401610ae8906133e3565b5050506000918252506007602052604090206001810154815460029092015490926001600160a01b0390921691565b60006001600160a01b03821661182b5760405162461bcd60e51b815260206004820152602760248201527f4e46543a2062616c616e636520717565727920666f7220746865207a65726f206044820152666164647265737360c81b6064820152608401610ae8565b506001600160a01b03166000908152600d602052604090205490565b82828260028054141561186c5760405162461bcd60e51b8152600401610ae8906132e0565b6002805560008061187c8861175b565b50915091508134116118dc5760405162461bcd60e51b8152602060048201526024808201527f4e657720626964206d7573742065786365656420746865206578697374696e67604482015263206f6e6560e01b6064820152608401610ae8565b6000821561191c576040516001600160a01b0383169084156108fc029085906000818181858888f1935050505015801561191a573d6000803e3d6000fd5b505b346119268a611eb9565b101561193c5761193589611eb9565b905061193f565b50345b600089815260076020526040908190206001810183905580546001600160a01b03191633178155426002909101555181908a907f223d0d5db4846341da7a5cc902b1a7c597e63b6c73b1c6267dc931d290c7affb906119a1908c908c90613452565b60405180910390a3346119b38a611eb9565b10156119fa57336108fc6119c68b611eb9565b6119d090346133cc565b6040518115909202916000818181858888f193505050501580156119f8573d6000803e3d6000fd5b505b5050600160025550600080611a0e8561175b565b50915091506000611a1e86611eb9565b118015611a33575081611a3086611eb9565b11155b15611b28576000611a44838761263f565b611a4e90846133cc565b9050611a59866116ce565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a384604051611a9e91815260200190565b60405180910390a4611aaf866116ce565b6001600160a01b03166108fc829081150290604051600060405180830381858888f19350505050158015611ae7573d6000803e3d6000fd5b50600086815260076020908152604080832080546001600160a01b031916815560018101849055600201839055600690915281205561119e611193876116ce565b5050505050505050565b6000546001600160a01b03163314611b5c5760405162461bcd60e51b8152600401610ae890613345565b6000918252600f6020526040909120805463ffffffff191663ffffffff909216919091179055565b600082815260036020526040902080546060919083908110611ba857611ba8613295565b906000526020600020018054611bbd906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054611be9906132ab565b8015611c365780601f10611c0b57610100808354040283529160200191611c36565b820191906000526020600020905b815481529060010190602001808311611c1957829003601f168201915b5050505050905092915050565b6000546001600160a01b03163314611c6d5760405162461bcd60e51b8152600401610ae890613345565b806011548110611c8f5760405162461bcd60e51b8152600401610ae890613395565b6000828152600e60209081526040808320805460018101825590845282842082519384019283905292849052610d5f93920191612be7565b6000546001600160a01b03163314611cf15760405162461bcd60e51b8152600401610ae890613345565b63ffffffff909216600090815260046020526040902080546001600160a01b039092166001600160a01b031990921691909117815560010155565b6060600b8054610a41906132ab565b600082815260106020526040902054601154606091908110611d6f5760405162461bcd60e51b8152600401610ae890613395565b6000848152601060209081526040808320548352600e90915290208054849081106114f9576114f9613295565b6000546001600160a01b031615611deb5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610ae8565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620151806005558251611e4490600a906020860190612be7565b508151611e5890600b906020850190612be7565b506000805260046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec80546001600160a01b031916331790557f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ed555050565b6000818152600c60205260408120546001600160a01b031680611eee5760405162461bcd60e51b8152600401610ae8906133e3565b505060009081526006602052604090205490565b6000546001600160a01b03163314611f2c5760405162461bcd60e51b8152600401610ae890613345565b610eea848484846129dc565b6000611f4733868686866126d2565b7f3ba9136826ac751de05d770d8d34fa4440ada49a5fb0e9aa1678aece66dad9768383604051611f78929190613452565b60405180910390a1506001949350505050565b6000546001600160a01b03163314611fb55760405162461bcd60e51b8152600401610ae890613345565b60005b82811015610d5f576000828152600e60209081526040808320805460018101825590845282842082519384019283905292849052611ff893920191612be7565b50806120038161337a565b915050611fb8565b600033612017836116ce565b6001600160a01b03161461203d5760405162461bcd60e51b8152600401610ae890613466565b6001600160a01b0383166120635760405162461bcd60e51b8152600401610ae8906134ac565b600082815260066020526040812055336000908152600d602052604081208054600192906120929084906133cc565b90915550506001600160a01b0383166000908152600d602052604081208054600192906120c090849061332d565b90915550506000828152600c602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233916000805160206135ae8339815191529190a450600192915050565b6000546001600160a01b0316331461213b5760405162461bcd60e51b8152600401610ae890613345565b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b606081601154811061218a5760405162461bcd60e51b8152600401610ae890613395565b6000838152600e6020908152604080832080548251818502810185019093528083529193909284015b828210156114a85783829060005260206000200180546121d2906132ab565b80601f01602080910402602001604051908101604052809291908181526020018280546121fe906132ab565b801561224b5780601f106122205761010080835404028352916020019161224b565b820191906000526020600020905b81548152906001019060200180831161222e57829003601f168201915b5050505050815260200190600101906121b3565b3360009081526001602052604090205460ff166122b55760405162461bcd60e51b8152602060048201526014602482015273135a5b9d195c881c9bdb19481c995c5d5a5c995960621b6044820152606401610ae8565b6001600160a01b03851661230b5760405162461bcd60e51b815260206004820152601d60248201527f4e46543a206d696e7420746f20746865207a65726f20616464726573730000006044820152606401610ae8565b6000848152600c60205260409020546001600160a01b03161561236c5760405162461bcd60e51b81526020600482015260196024820152781391950e881d1bdad95b88185b1c9958591e481b5a5b9d1959603a1b6044820152606401610ae8565b61237584612a17565b6000848152601060209081526040808320869055858352600f8252808320548784526008909252909120805463ffffffff191663ffffffff9092169190911790556123c184838361256b565b6001600160a01b0385166000908152600d602052604081208054600192906123ea90849061332d565b90915550506000848152600c602052604080822080546001600160a01b0319166001600160a01b03891690811790915590518692906000805160206135ae833981519152908290a45050505050565b6000546001600160a01b031633146124635760405162461bcd60e51b8152600401610ae890613345565b6001600160a01b0381166124c85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ae8565b6124d181612a66565b50565b6000546001600160a01b031633146124fe5760405162461bcd60e51b8152600401610ae890613345565b60095481116125665760405162461bcd60e51b815260206004820152602e60248201527f6e6578745f6d696e745f6964206d75737420626520686967686572207468616e60448201526d081b185cdd081d1bdad95b88125160921b6064820152608401610ae8565b600955565b6000838152600360209081526040822080546001810182559083529120610eea91018383612c6b565b6125ed82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508981526003602052604090208054909350889250821090506112d4576112d4613295565b6000858152600360205260409020805485908110610e9057610e90613295565b600061261b33600954612ab6565b5060098054908190600061262e8361337a565b919050555061263c81612a17565b90565b60008181526008602090815260408083205463ffffffff168084526004909252822080546001909101546001600160a01b039091169083620186a061268483896134ed565b61268e919061350c565b6040519091506001600160a01b0384169082156108fc029083906000818181858888f193505050501580156126c7573d6000803e3d6000fd5b509695505050505050565b846001600160a01b03166126e5846116ce565b6001600160a01b03161461270b5760405162461bcd60e51b8152600401610ae890613466565b6001600160a01b0384166127315760405162461bcd60e51b8152600401610ae8906134ac565b6000838152600660205260408120556001600160a01b0385166000908152600d602052604081208054600192906127699084906133cc565b90915550506001600160a01b0384166000908152600d6020526040812080546001929061279790849061332d565b90915550506000838152600c6020526040902080546001600160a01b0319166001600160a01b0386169081179091553b1561284557604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612800903390899088908890889060040161352e565b6020604051808303816000875af115801561281f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612843919061356d565b505b82846001600160a01b0316866001600160a01b03166000805160206135ae83398151915260405160405180910390a45050505050565b80516060908390839061289057612890613597565b6000815183516128a0919061332d565b67ffffffffffffffff8111156128b8576128b8612daf565b6040519080825280601f01601f1916602001820160405280156128e2576020820181803683370190505b509050806000805b855182101561295a5785828151811061290557612905613295565b01602001516001600160f81b031916838261291f8161337a565b93508151811061293157612931613295565b60200101906001600160f81b031916908160001a905350816129528161337a565b9250506128ea565b600091505b84518210156129cf5784828151811061297a5761297a613295565b01602001516001600160f81b03191683826129948161337a565b9350815181106129a6576129a6613295565b60200101906001600160f81b031916908160001a905350816129c78161337a565b92505061295f565b5090979650505050505050565b600084815260036020526040902080548391839186908110612a0057612a00613295565b906000526020600020019190610ead929190612c6b565b6000818152600360205260409020546124d1576000818152600360209081526040808320805460018101825590845282842082519384019283905292849052612a6293920191612be7565b5050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612a6282826001600160a01b038216612b115760405162461bcd60e51b815260206004820152601d60248201527f4e46543a206d696e7420746f20746865207a65726f20616464726573730000006044820152606401610ae8565b6000818152600c60205260409020546001600160a01b031615612b725760405162461bcd60e51b81526020600482015260196024820152781391950e881d1bdad95b88185b1c9958591e481b5a5b9d1959603a1b6044820152606401610ae8565b6001600160a01b0382166000908152600d60205260408120805460019290612b9b90849061332d565b90915550506000818152600c602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392906000805160206135ae833981519152908290a45050565b828054612bf3906132ab565b90600052602060002090601f016020900481019282612c155760008555612c5b565b82601f10612c2e57805160ff1916838001178555612c5b565b82800160010185558215612c5b579182015b82811115612c5b578251825591602001919060010190612c40565b50612c67929150612cdf565b5090565b828054612c77906132ab565b90600052602060002090601f016020900481019282612c995760008555612c5b565b82601f10612cb25782800160ff19823516178555612c5b565b82800160010185558215612c5b579182015b82811115612c5b578235825591602001919060010190612cc4565b5b80821115612c675760008155600101612ce0565b600060208284031215612d0657600080fd5b5035919050565b6000815180845260005b81811015612d3357602081850181015186830182015201612d17565b81811115612d45576000602083870101525b50601f01601f19169290920160200192915050565b602081526000612d6d6020830184612d0d565b9392505050565b60008060408385031215612d8757600080fd5b50508035926020909101359150565b803563ffffffff81168114612daa57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112612dd657600080fd5b813567ffffffffffffffff80821115612df157612df1612daf565b604051601f8301601f19908116603f01168101908282118183101715612e1957612e19612daf565b81604052838152866020858801011115612e3257600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612e6557600080fd5b612e6e83612d96565b9150602083013567ffffffffffffffff811115612e8a57600080fd5b612e9685828601612dc5565b9150509250929050565b60008083601f840112612eb257600080fd5b50813567ffffffffffffffff811115612eca57600080fd5b602083019150836020828501011115612ee257600080fd5b9250929050565b600080600060408486031215612efe57600080fd5b83359250602084013567ffffffffffffffff811115612f1c57600080fd5b612f2886828701612ea0565b9497909650939450505050565b600080600060608486031215612f4a57600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612f6f57600080fd5b612f7b86828701612dc5565b9150509250925092565b60008060008060608587031215612f9b57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612fc057600080fd5b612fcc87828801612ea0565b95989497509550505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561302057828403895261300e848351612d0d565b98850198935090840190600101612ff6565b5091979650505050505050565b602081526000612d6d6020830184612fd8565b602081526000825160208084015261305b6040840182612fd8565b949350505050565b80356001600160a01b0381168114612daa57600080fd5b60006020828403121561308c57600080fd5b612d6d82613063565b600080604083850312156130a857600080fd5b823591506130b860208401612d96565b90509250929050565b6000602082840312156130d357600080fd5b612d6d82612d96565b6000806000606084860312156130f157600080fd5b6130fa84612d96565b925061310860208501613063565b9150604084013590509250925092565b60008060006060848603121561312d57600080fd5b833567ffffffffffffffff8082111561314557600080fd5b61315187838801612dc5565b9450602086013591508082111561316757600080fd5b5061317486828701612dc5565b925050604084013590509250925092565b6000806000806060858703121561319b57600080fd5b6131a485613063565b935060208501359250604085013567ffffffffffffffff811115612fc057600080fd5b600080604083850312156131da57600080fd5b6131e383613063565b946020939093013593505050565b6000806040838503121561320457600080fd5b61320d83613063565b91506020830135801515811461322257600080fd5b809150509250929050565b60008060008060006080868803121561324557600080fd5b61324e86613063565b94506020860135935060408601359250606086013567ffffffffffffffff81111561327857600080fd5b61328488828901612ea0565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806132bf57607f821691505b602082108114156114af57634e487b7160e01b600052602260045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000821982111561334057613340613317565b500190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060001982141561338e5761338e613317565b5060010190565b6020808252601c908201527f5175657269656420636c61737320646f6573206e6f7420657869737400000000604082015260600190565b6000828210156133de576133de613317565b500390565b60208082526026908201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604082015265103a37b5b2b760d11b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061305b602083018486613429565b60208082526026908201527f4e46543a207472616e73666572206f6620746f6b656e2074686174206973206e60408201526537ba1037bbb760d11b606082015260800190565b60208082526021908201527f4e46543a207472616e7366657220746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b600081600019048311821515161561350757613507613317565b500290565b60008261352957634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03868116825285166020820152604081018490526080606082018190526000906135629083018486613429565b979650505050505050565b60006020828403121561357f57600080fd5b81516001600160e01b031981168114612d6d57600080fd5b634e487b7160e01b600052600160045260246000fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200945c923696081776802a08dfb59e366149360ccd3f69c5c3307a3ce16b1a7b164736f6c634300080c0033
Deployed ByteCode
0x6080604052600436106102935760003560e01c806373baa6511161015a578063bb053717116100c1578063d75d1e661161007a578063d75d1e661461089a578063e29fb036146108e2578063e6470059146108f8578063eed9940814610918578063f2fde38b14610938578063f44079861461095857600080fd5b8063bb053717146107cd578063be45fd62146107ed578063be6710581461080d578063c1940f1b1461082d578063c98e0c3c1461085a578063cb177b1e1461087a57600080fd5b80638e39e18c116101135780638e39e18c14610722578063911006951461074257806395d89b41146107585780639de4792e1461076d578063b119490e1461078d578063b9186d7d146107ad57600080fd5b806373baa6511461063257806374c29ce31461064557806378317f3f146106a45780637ab56e52146106c457806380483a6a146106e45780638da5cb5b1461070457600080fd5b80633e0bb783116101fe578063543dc7fa116101b7578063543dc7fa146105235780635a3b7e42146105435780636352211e14610577578063648fbe40146105af578063649ccc14146105cf57806370a082311461061257600080fd5b80633e0bb783146104395780634774d93f146104595780634bb2ddd4146104795780634c1720a4146104a65780634edea111146104c6578063510910bb146104f357600080fd5b8063290e008c11610250578063290e008c146103795780632a6d3f44146103995780633054d9cb146103b95780633add5fa1146103d95780633c65b3eb146103f95780633d8073f11461041957600080fd5b806302ff368a1461029857806306fdde03146102ce5780630eaaf4c8146102e35780631d734c8f146103135780631f38e6541461033757806325498c7514610359575b600080fd5b3480156102a457600080fd5b506102b86102b3366004612cf4565b610978565b6040516102c59190612d5a565b60405180910390f35b3480156102da57600080fd5b506102b8610a32565b3480156102ef57600080fd5b506103036102fe366004612cf4565b610ac4565b60405190151581526020016102c5565b34801561031f57600080fd5b5061032960115481565b6040519081526020016102c5565b34801561034357600080fd5b50610357610352366004612d74565b610c2a565b005b34801561036557600080fd5b50610357610374366004612e52565b610c66565b34801561038557600080fd5b50610357610394366004612ee9565b610d01565b3480156103a557600080fd5b506103036103b4366004612ee9565b610d64565b3480156103c557600080fd5b506103576103d4366004612f35565b610e21565b3480156103e557600080fd5b506103576103f4366004612f85565b610eb4565b34801561040557600080fd5b50610329610414366004612cf4565b610ef0565b34801561042557600080fd5b50610357610434366004612f85565b610fbb565b34801561044557600080fd5b506102b8610454366004612d74565b6111a9565b34801561046557600080fd5b50610357610474366004612f35565b611262565b34801561048557600080fd5b50610499610494366004612cf4565b611395565b6040516102c5919061302d565b3480156104b257600080fd5b506102b86104c1366004612d74565b6114b5565b3480156104d257600080fd5b506104e66104e1366004612cf4565b611595565b6040516102c59190613040565b3480156104ff57600080fd5b5061030361050e36600461307a565b60016020526000908152604090205460ff1681565b34801561052f57600080fd5b5061032961053e366004612cf4565b61168a565b34801561054f57600080fd5b5060408051808201909152600b81526a10d85b1b1a5cdd1bd3919560aa1b60208201526102b8565b34801561058357600080fd5b50610597610592366004612cf4565b6116ce565b6040516001600160a01b0390911681526020016102c5565b3480156105bb57600080fd5b506103576105ca366004613095565b611709565b3480156105db57600080fd5b506105ef6105ea366004612cf4565b61175b565b604080519384526001600160a01b039092166020840152908201526060016102c5565b34801561061e57600080fd5b5061032961062d36600461307a565b6117c3565b610357610640366004612ee9565b611847565b34801561065157600080fd5b506106856106603660046130c1565b600460205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b0390931683526020830191909152016102c5565b3480156106b057600080fd5b506103576106bf366004613095565b611b32565b3480156106d057600080fd5b506102b86106df366004612d74565b611b84565b3480156106f057600080fd5b506103576106ff366004612cf4565b611c43565b34801561071057600080fd5b506000546001600160a01b0316610597565b34801561072e57600080fd5b5061035761073d3660046130dc565b611cc7565b34801561074e57600080fd5b5061032960055481565b34801561076457600080fd5b506102b8611d2c565b34801561077957600080fd5b506102b8610788366004612d74565b611d3b565b34801561079957600080fd5b506103576107a8366004613118565b611d9c565b3480156107b957600080fd5b506103296107c8366004612cf4565b611eb9565b3480156107d957600080fd5b506103576107e8366004612f85565b611f02565b3480156107f957600080fd5b50610303610808366004613185565b611f38565b34801561081957600080fd5b50610357610828366004612d74565b611f8b565b34801561083957600080fd5b50610329610848366004612cf4565b60106020526000908152604090205481565b34801561086657600080fd5b506103036108753660046131c7565b61200b565b34801561088657600080fd5b506103576108953660046131f1565b612111565b3480156108a657600080fd5b506108cd6108b5366004612cf4565b600f6020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016102c5565b3480156108ee57600080fd5b5061032960095481565b34801561090457600080fd5b50610499610913366004612cf4565b612166565b34801561092457600080fd5b5061035761093336600461322d565b61225f565b34801561094457600080fd5b5061035761095336600461307a565b612439565b34801561096457600080fd5b50610357610973366004612cf4565b6124d4565b600081815260036020526040812080546060929061099857610998613295565b9060005260206000200180546109ad906132ab565b80601f01602080910402602001604051908101604052809291908181526020018280546109d9906132ab565b8015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b50505050509050919050565b6060600a8054610a41906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6d906132ab565b8015610aba5780601f10610a8f57610100808354040283529160200191610aba565b820191906000526020600020905b815481529060010190602001808311610a9d57829003601f168201915b5050505050905090565b6000600280541415610af15760405162461bcd60e51b8152600401610ae8906132e0565b60405180910390fd5b6002805560008080610b028561175b565b91945092509050336001600160a01b03831614610b6c5760405162461bcd60e51b815260206004820152602260248201527f43616e206e6f7420776974686472617720736f6d656f6e6520656c73657320626044820152611a5960f21b6064820152608401610ae8565b600554610b79908261332d565b4211610bbc5760405162461bcd60e51b8152602060048201526012602482015271109a59081a5cc81d1a5b594b5b1bd8dad95960721b6044820152606401610ae8565b6040516001600160a01b0383169084156108fc029085906000818181858888f19350505050158015610bf2573d6000803e3d6000fd5b5050506000928352505060076020526040812080546001600160a01b0319168155600180820183905560029182019290925581905590565b6000546001600160a01b03163314610c545760405162461bcd60e51b8152600401610ae890613345565b60009182526010602052604090912055565b6000546001600160a01b03163314610c905760405162461bcd60e51b8152600401610ae890613345565b6011546000908152600e6020908152604082208054600181018255908352918190208351610cc5939190910191840190612be7565b50601180546000908152600f60205260408120805463ffffffff191663ffffffff861617905581549190610cf88361337a565b91905055505050565b33610d146000546001600160a01b031690565b6001600160a01b03161480610d3857503360009081526001602052604090205460ff165b610d545760405162461bcd60e51b8152600401610ae890613345565b610d5f83838361256b565b505050565b6000610d6f846116ce565b6001600160a01b0316336001600160a01b031614610dde5760405162461bcd60e51b815260206004820152602660248201527f4e46543a206f6e6c79206f776e65722063616e206368616e6765204e465420636044820152651bdb9d195b9d60d21b6064820152608401610ae8565b600084815260036020526040812080548592859291610dff57610dff613295565b906000526020600020019190610e16929190612c6b565b506001949350505050565b6000546001600160a01b03163314610e4b5760405162461bcd60e51b8152600401610ae890613345565b826011548110610e6d5760405162461bcd60e51b8152600401610ae890613395565b6000848152600e60205260409020805483919085908110610e9057610e90613295565b906000526020600020019080519060200190610ead929190612be7565b5050505050565b6000546001600160a01b03163314610ede5760405162461bcd60e51b8152600401610ae890613345565b610eea84848484612594565b50505050565b6000816011548110610f145760405162461bcd60e51b8152600401610ae890613395565b3360009081526001602052604090205460ff16610f6a5760405162461bcd60e51b8152602060048201526014602482015273135a5b9d195c881c9bdb19481c995c5d5a5c995960621b6044820152606401610ae8565b610f7261260d565b6000818152601060209081526040808320879055958252600f8152858220548383526008909152949020805463ffffffff191663ffffffff909516949094179093555090919050565b838282600280541415610fe05760405162461bcd60e51b8152600401610ae8906132e0565b6002805533610fee886116ce565b6001600160a01b0316146110595760405162461bcd60e51b815260206004820152602c60248201527f53657474696e672061736b73206973206f6e6c7920616c6c6f77656420666f7260448201526b206f776e6564204e4654732160a01b6064820152608401610ae8565b60008781526006602052604081208790556001600255806110798561175b565b5091509150600061108986611eb9565b11801561109e57508161109b86611eb9565b11155b1561119e5760006110af838761263f565b6110b990846133cc565b90506110c4866116ce565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a38460405161110991815260200190565b60405180910390a461111a866116ce565b6001600160a01b03166108fc829081150290604051600060405180830381858888f19350505050158015611152573d6000803e3d6000fd5b50600086815260076020908152604080832080546001600160a01b031916815560018101849055600201839055600690915281205561119c611193876116ce565b838888886126d2565b505b505050505050505050565b600e60205281600052604060002081815481106111c557600080fd5b906000526020600020016000915091505080546111e1906132ab565b80601f016020809104026020016040519081016040528092919081815260200182805461120d906132ab565b801561125a5780601f1061122f5761010080835404028352916020019161125a565b820191906000526020600020905b81548152906001019060200180831161123d57829003601f168201915b505050505081565b6000546001600160a01b0316331461128c5760405162461bcd60e51b8152600401610ae890613345565b8260115481106112ae5760405162461bcd60e51b8152600401610ae890613395565b6000848152600e602052604090208054611375918491869081106112d4576112d4613295565b9060005260206000200180546112e9906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054611315906132ab565b80156113625780601f1061133757610100808354040283529160200191611362565b820191906000526020600020905b81548152906001019060200180831161134557829003601f168201915b505050505061287b90919063ffffffff16565b6000858152600e60205260409020805485908110610e9057610e90613295565b6000818152601060205260409020546011546060919081106113c95760405162461bcd60e51b8152600401610ae890613395565b6000838152601060209081526040808320548352600e825280832080548251818502810185019093528083529193909284015b828210156114a857838290600052602060002001805461141b906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054611447906132ab565b80156114945780601f1061146957610100808354040283529160200191611494565b820191906000526020600020905b81548152906001019060200180831161147757829003601f168201915b5050505050815260200190600101906113fc565b5050505091505b50919050565b60608260115481106114d95760405162461bcd60e51b8152600401610ae890613395565b6000848152600e602052604090208054849081106114f9576114f9613295565b90600052602060002001805461150e906132ab565b80601f016020809104026020016040519081016040528092919081815260200182805461153a906132ab565b80156115875780601f1061155c57610100808354040283529160200191611587565b820191906000526020600020905b81548152906001019060200180831161156a57829003601f168201915b505050505091505092915050565b604080516020808201835260608252600084815260038252838120845181548085028201870187529381018481529495909491938593859285015b8282101561167c5783829060005260206000200180546115ef906132ab565b80601f016020809104026020016040519081016040528092919081815260200182805461161b906132ab565b80156116685780601f1061163d57610100808354040283529160200191611668565b820191906000526020600020905b81548152906001019060200180831161164b57829003601f168201915b5050505050815260200190600101906115d0565b505050915250909392505050565b60008181526010602052604081205460115481106116ba5760405162461bcd60e51b8152600401610ae890613395565b505060009081526010602052604090205490565b6000818152600c60205260408120546001600160a01b0316806117035760405162461bcd60e51b8152600401610ae8906133e3565b92915050565b6000546001600160a01b031633146117335760405162461bcd60e51b8152600401610ae890613345565b600091825260086020526040909120805463ffffffff191663ffffffff909216919091179055565b6000818152600c6020526040812054819081906001600160a01b0316806117945760405162461bcd60e51b8152600401610ae8906133e3565b5050506000918252506007602052604090206001810154815460029092015490926001600160a01b0390921691565b60006001600160a01b03821661182b5760405162461bcd60e51b815260206004820152602760248201527f4e46543a2062616c616e636520717565727920666f7220746865207a65726f206044820152666164647265737360c81b6064820152608401610ae8565b506001600160a01b03166000908152600d602052604090205490565b82828260028054141561186c5760405162461bcd60e51b8152600401610ae8906132e0565b6002805560008061187c8861175b565b50915091508134116118dc5760405162461bcd60e51b8152602060048201526024808201527f4e657720626964206d7573742065786365656420746865206578697374696e67604482015263206f6e6560e01b6064820152608401610ae8565b6000821561191c576040516001600160a01b0383169084156108fc029085906000818181858888f1935050505015801561191a573d6000803e3d6000fd5b505b346119268a611eb9565b101561193c5761193589611eb9565b905061193f565b50345b600089815260076020526040908190206001810183905580546001600160a01b03191633178155426002909101555181908a907f223d0d5db4846341da7a5cc902b1a7c597e63b6c73b1c6267dc931d290c7affb906119a1908c908c90613452565b60405180910390a3346119b38a611eb9565b10156119fa57336108fc6119c68b611eb9565b6119d090346133cc565b6040518115909202916000818181858888f193505050501580156119f8573d6000803e3d6000fd5b505b5050600160025550600080611a0e8561175b565b50915091506000611a1e86611eb9565b118015611a33575081611a3086611eb9565b11155b15611b28576000611a44838761263f565b611a4e90846133cc565b9050611a59866116ce565b6001600160a01b0316826001600160a01b0316877fc9b9afd9684b23c6b22a41016c08e8954ac118220c0a52f00b8774c46580e9a384604051611a9e91815260200190565b60405180910390a4611aaf866116ce565b6001600160a01b03166108fc829081150290604051600060405180830381858888f19350505050158015611ae7573d6000803e3d6000fd5b50600086815260076020908152604080832080546001600160a01b031916815560018101849055600201839055600690915281205561119e611193876116ce565b5050505050505050565b6000546001600160a01b03163314611b5c5760405162461bcd60e51b8152600401610ae890613345565b6000918252600f6020526040909120805463ffffffff191663ffffffff909216919091179055565b600082815260036020526040902080546060919083908110611ba857611ba8613295565b906000526020600020018054611bbd906132ab565b80601f0160208091040260200160405190810160405280929190818152602001828054611be9906132ab565b8015611c365780601f10611c0b57610100808354040283529160200191611c36565b820191906000526020600020905b815481529060010190602001808311611c1957829003601f168201915b5050505050905092915050565b6000546001600160a01b03163314611c6d5760405162461bcd60e51b8152600401610ae890613345565b806011548110611c8f5760405162461bcd60e51b8152600401610ae890613395565b6000828152600e60209081526040808320805460018101825590845282842082519384019283905292849052610d5f93920191612be7565b6000546001600160a01b03163314611cf15760405162461bcd60e51b8152600401610ae890613345565b63ffffffff909216600090815260046020526040902080546001600160a01b039092166001600160a01b031990921691909117815560010155565b6060600b8054610a41906132ab565b600082815260106020526040902054601154606091908110611d6f5760405162461bcd60e51b8152600401610ae890613395565b6000848152601060209081526040808320548352600e90915290208054849081106114f9576114f9613295565b6000546001600160a01b031615611deb5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610ae8565b600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620151806005558251611e4490600a906020860190612be7565b508151611e5890600b906020850190612be7565b506000805260046020527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec80546001600160a01b031916331790557f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ed555050565b6000818152600c60205260408120546001600160a01b031680611eee5760405162461bcd60e51b8152600401610ae8906133e3565b505060009081526006602052604090205490565b6000546001600160a01b03163314611f2c5760405162461bcd60e51b8152600401610ae890613345565b610eea848484846129dc565b6000611f4733868686866126d2565b7f3ba9136826ac751de05d770d8d34fa4440ada49a5fb0e9aa1678aece66dad9768383604051611f78929190613452565b60405180910390a1506001949350505050565b6000546001600160a01b03163314611fb55760405162461bcd60e51b8152600401610ae890613345565b60005b82811015610d5f576000828152600e60209081526040808320805460018101825590845282842082519384019283905292849052611ff893920191612be7565b50806120038161337a565b915050611fb8565b600033612017836116ce565b6001600160a01b03161461203d5760405162461bcd60e51b8152600401610ae890613466565b6001600160a01b0383166120635760405162461bcd60e51b8152600401610ae8906134ac565b600082815260066020526040812055336000908152600d602052604081208054600192906120929084906133cc565b90915550506001600160a01b0383166000908152600d602052604081208054600192906120c090849061332d565b90915550506000828152600c602052604080822080546001600160a01b0319166001600160a01b0387169081179091559051849233916000805160206135ae8339815191529190a450600192915050565b6000546001600160a01b0316331461213b5760405162461bcd60e51b8152600401610ae890613345565b6001600160a01b03919091166000908152600160205260409020805460ff1916911515919091179055565b606081601154811061218a5760405162461bcd60e51b8152600401610ae890613395565b6000838152600e6020908152604080832080548251818502810185019093528083529193909284015b828210156114a85783829060005260206000200180546121d2906132ab565b80601f01602080910402602001604051908101604052809291908181526020018280546121fe906132ab565b801561224b5780601f106122205761010080835404028352916020019161224b565b820191906000526020600020905b81548152906001019060200180831161222e57829003601f168201915b5050505050815260200190600101906121b3565b3360009081526001602052604090205460ff166122b55760405162461bcd60e51b8152602060048201526014602482015273135a5b9d195c881c9bdb19481c995c5d5a5c995960621b6044820152606401610ae8565b6001600160a01b03851661230b5760405162461bcd60e51b815260206004820152601d60248201527f4e46543a206d696e7420746f20746865207a65726f20616464726573730000006044820152606401610ae8565b6000848152600c60205260409020546001600160a01b03161561236c5760405162461bcd60e51b81526020600482015260196024820152781391950e881d1bdad95b88185b1c9958591e481b5a5b9d1959603a1b6044820152606401610ae8565b61237584612a17565b6000848152601060209081526040808320869055858352600f8252808320548784526008909252909120805463ffffffff191663ffffffff9092169190911790556123c184838361256b565b6001600160a01b0385166000908152600d602052604081208054600192906123ea90849061332d565b90915550506000848152600c602052604080822080546001600160a01b0319166001600160a01b03891690811790915590518692906000805160206135ae833981519152908290a45050505050565b6000546001600160a01b031633146124635760405162461bcd60e51b8152600401610ae890613345565b6001600160a01b0381166124c85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ae8565b6124d181612a66565b50565b6000546001600160a01b031633146124fe5760405162461bcd60e51b8152600401610ae890613345565b60095481116125665760405162461bcd60e51b815260206004820152602e60248201527f6e6578745f6d696e745f6964206d75737420626520686967686572207468616e60448201526d081b185cdd081d1bdad95b88125160921b6064820152608401610ae8565b600955565b6000838152600360209081526040822080546001810182559083529120610eea91018383612c6b565b6125ed82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508981526003602052604090208054909350889250821090506112d4576112d4613295565b6000858152600360205260409020805485908110610e9057610e90613295565b600061261b33600954612ab6565b5060098054908190600061262e8361337a565b919050555061263c81612a17565b90565b60008181526008602090815260408083205463ffffffff168084526004909252822080546001909101546001600160a01b039091169083620186a061268483896134ed565b61268e919061350c565b6040519091506001600160a01b0384169082156108fc029083906000818181858888f193505050501580156126c7573d6000803e3d6000fd5b509695505050505050565b846001600160a01b03166126e5846116ce565b6001600160a01b03161461270b5760405162461bcd60e51b8152600401610ae890613466565b6001600160a01b0384166127315760405162461bcd60e51b8152600401610ae8906134ac565b6000838152600660205260408120556001600160a01b0385166000908152600d602052604081208054600192906127699084906133cc565b90915550506001600160a01b0384166000908152600d6020526040812080546001929061279790849061332d565b90915550506000838152600c6020526040902080546001600160a01b0319166001600160a01b0386169081179091553b1561284557604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612800903390899088908890889060040161352e565b6020604051808303816000875af115801561281f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612843919061356d565b505b82846001600160a01b0316866001600160a01b03166000805160206135ae83398151915260405160405180910390a45050505050565b80516060908390839061289057612890613597565b6000815183516128a0919061332d565b67ffffffffffffffff8111156128b8576128b8612daf565b6040519080825280601f01601f1916602001820160405280156128e2576020820181803683370190505b509050806000805b855182101561295a5785828151811061290557612905613295565b01602001516001600160f81b031916838261291f8161337a565b93508151811061293157612931613295565b60200101906001600160f81b031916908160001a905350816129528161337a565b9250506128ea565b600091505b84518210156129cf5784828151811061297a5761297a613295565b01602001516001600160f81b03191683826129948161337a565b9350815181106129a6576129a6613295565b60200101906001600160f81b031916908160001a905350816129c78161337a565b92505061295f565b5090979650505050505050565b600084815260036020526040902080548391839186908110612a0057612a00613295565b906000526020600020019190610ead929190612c6b565b6000818152600360205260409020546124d1576000818152600360209081526040808320805460018101825590845282842082519384019283905292849052612a6293920191612be7565b5050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612a6282826001600160a01b038216612b115760405162461bcd60e51b815260206004820152601d60248201527f4e46543a206d696e7420746f20746865207a65726f20616464726573730000006044820152606401610ae8565b6000818152600c60205260409020546001600160a01b031615612b725760405162461bcd60e51b81526020600482015260196024820152781391950e881d1bdad95b88185b1c9958591e481b5a5b9d1959603a1b6044820152606401610ae8565b6001600160a01b0382166000908152600d60205260408120805460019290612b9b90849061332d565b90915550506000818152600c602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392906000805160206135ae833981519152908290a45050565b828054612bf3906132ab565b90600052602060002090601f016020900481019282612c155760008555612c5b565b82601f10612c2e57805160ff1916838001178555612c5b565b82800160010185558215612c5b579182015b82811115612c5b578251825591602001919060010190612c40565b50612c67929150612cdf565b5090565b828054612c77906132ab565b90600052602060002090601f016020900481019282612c995760008555612c5b565b82601f10612cb25782800160ff19823516178555612c5b565b82800160010185558215612c5b579182015b82811115612c5b578235825591602001919060010190612cc4565b5b80821115612c675760008155600101612ce0565b600060208284031215612d0657600080fd5b5035919050565b6000815180845260005b81811015612d3357602081850181015186830182015201612d17565b81811115612d45576000602083870101525b50601f01601f19169290920160200192915050565b602081526000612d6d6020830184612d0d565b9392505050565b60008060408385031215612d8757600080fd5b50508035926020909101359150565b803563ffffffff81168114612daa57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112612dd657600080fd5b813567ffffffffffffffff80821115612df157612df1612daf565b604051601f8301601f19908116603f01168101908282118183101715612e1957612e19612daf565b81604052838152866020858801011115612e3257600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215612e6557600080fd5b612e6e83612d96565b9150602083013567ffffffffffffffff811115612e8a57600080fd5b612e9685828601612dc5565b9150509250929050565b60008083601f840112612eb257600080fd5b50813567ffffffffffffffff811115612eca57600080fd5b602083019150836020828501011115612ee257600080fd5b9250929050565b600080600060408486031215612efe57600080fd5b83359250602084013567ffffffffffffffff811115612f1c57600080fd5b612f2886828701612ea0565b9497909650939450505050565b600080600060608486031215612f4a57600080fd5b8335925060208401359150604084013567ffffffffffffffff811115612f6f57600080fd5b612f7b86828701612dc5565b9150509250925092565b60008060008060608587031215612f9b57600080fd5b8435935060208501359250604085013567ffffffffffffffff811115612fc057600080fd5b612fcc87828801612ea0565b95989497509550505050565b600081518084526020808501808196508360051b8101915082860160005b8581101561302057828403895261300e848351612d0d565b98850198935090840190600101612ff6565b5091979650505050505050565b602081526000612d6d6020830184612fd8565b602081526000825160208084015261305b6040840182612fd8565b949350505050565b80356001600160a01b0381168114612daa57600080fd5b60006020828403121561308c57600080fd5b612d6d82613063565b600080604083850312156130a857600080fd5b823591506130b860208401612d96565b90509250929050565b6000602082840312156130d357600080fd5b612d6d82612d96565b6000806000606084860312156130f157600080fd5b6130fa84612d96565b925061310860208501613063565b9150604084013590509250925092565b60008060006060848603121561312d57600080fd5b833567ffffffffffffffff8082111561314557600080fd5b61315187838801612dc5565b9450602086013591508082111561316757600080fd5b5061317486828701612dc5565b925050604084013590509250925092565b6000806000806060858703121561319b57600080fd5b6131a485613063565b935060208501359250604085013567ffffffffffffffff811115612fc057600080fd5b600080604083850312156131da57600080fd5b6131e383613063565b946020939093013593505050565b6000806040838503121561320457600080fd5b61320d83613063565b91506020830135801515811461322257600080fd5b809150509250929050565b60008060008060006080868803121561324557600080fd5b61324e86613063565b94506020860135935060408601359250606086013567ffffffffffffffff81111561327857600080fd5b61328488828901612ea0565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806132bf57607f821691505b602082108114156114af57634e487b7160e01b600052602260045260246000fd5b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000821982111561334057613340613317565b500190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600060001982141561338e5761338e613317565b5060010190565b6020808252601c908201527f5175657269656420636c61737320646f6573206e6f7420657869737400000000604082015260600190565b6000828210156133de576133de613317565b500390565b60208082526026908201527f4e46543a206f776e657220717565727920666f72206e6f6e6578697374656e74604082015265103a37b5b2b760d11b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600061305b602083018486613429565b60208082526026908201527f4e46543a207472616e73666572206f6620746f6b656e2074686174206973206e60408201526537ba1037bbb760d11b606082015260800190565b60208082526021908201527f4e46543a207472616e7366657220746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b600081600019048311821515161561350757613507613317565b500290565b60008261352957634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b03868116825285166020820152604081018490526080606082018190526000906135629083018486613429565b979650505050505050565b60006020828403121561357f57600080fd5b81516001600160e01b031981168114612d6d57600080fd5b634e487b7160e01b600052600160045260246000fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212200945c923696081776802a08dfb59e366149360ccd3f69c5c3307a3ce16b1a7b164736f6c634300080c0033