Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Stays
- Optimization enabled
- true
- Compiler version
- v0.8.7+commit.e28d00a7
- Optimization runs
- 200
- Verified at
- 2022-03-31T19:06:04.787169Z
contracts/Stays.sol
// SPDX-License-Identifier: GPL
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./IStays.sol";
import "./StayEscrow.sol";
import "./libraries/StayTokenMeta.sol";
import "hardhat/console.sol";
contract Stays is IStays, StayEscrow, ERC721URIStorage, ERC721Enumerable, EIP712 {
using Counters for Counters.Counter;
Counters.Counter private _stayTokenIds;
uint32 public constant dayZero = 1645567342; // 22 Feb 2022
address private constant _ukraineDAO = 0x633b7218644b83D57d90e7299039ebAb19698e9C; // ukrainedao.eth https://twitter.com/Ukraine_DAO/status/1497274679823941632
uint8 private constant _ukraineDAOfee = 2; // percents
string public constant serviceURI = "https://localhost:3000/";
string private constant tokenImageURI = 'https://bafybeigg7mwwpnnm6mmk3twxc4arizoyc6ijnaye3pdciwcohheo7xi7hm.ipfs.dweb.link/token-image.png';
// Schema conformance URLs for reference
string public constant lodgingFacilitySchemaURI = "";
string public constant spaceSchemaURI = "";
string public constant staySchemaURI = "";
// Lodging Facility is any type of accommodation: hotel, hostel, apartment, etc.
struct LodgingFacility {
address owner;
bool active;
bool exists;
string dataURI; // must be conformant with "lodgingFacilitySchemaURI"
address fren;
}
// Space = Room Type
struct Space {
bytes32 lodgingFacilityId;
uint256 capacity; // number of rooms of this type
uint256 pricePerNightWei;
bool active;
bool exists;
string dataURI; // must be conformant with "spaceSchemaURI"
}
// Stay
struct Stay {
bytes32 spaceId;
uint256 startDay;
uint256 numberOfDays;
uint256 quantity;
bool checkIn;
bool checkOut;
}
bytes32[] private _lodgingFacilityIds;
// Facility owner => LodgingFacility[]
mapping (address => bytes32[]) private _facilityIdsByOwner;
// facilityId => LodgingFacility
mapping (bytes32 => LodgingFacility) public lodgingFacilities;
// facilityId => spaceId[]
mapping (bytes32 => bytes32[]) private _spaceIdsByFacilityId;
// spaceId => Space
mapping (bytes32 => Space) public spaces;
// spaceId => daysFromDayZero => numberOfBookings
mapping(bytes32 => mapping(uint256 => uint256)) private _booked;
// Stay token => Stay
mapping(uint256 => Stay) private _stays;
// spaceId => tokenId[]
mapping(bytes32 => uint256[]) private _stayTokens;
constructor() ERC721("StayToken", "ST22") EIP712("Stays", "1") {}
/**
* Modifiers
*/
modifier onlyLodgingFacilityOwner(bytes32 _lodgingFacilityId) {
require(
_msgSender() == lodgingFacilities[_lodgingFacilityId].owner,
"Only lodging facility owner is allowed"
);
_;
}
modifier onlySpaceOwner(bytes32 _spaceId) {
require(
_msgSender() == lodgingFacilities[spaces[_spaceId].lodgingFacilityId].owner,
"Only space owner is allowed"
);
_;
}
modifier onlyTokenOwner(uint256 _tokenId) {
require(
_msgSender() == ownerOf(_tokenId),
"Only stay token owner is allowed"
);
_;
}
/**
* Lodging Facilities Getters
*/
// All registered Ids
function getAllLodgingFacilityIds() public view override returns (bytes32[] memory) {
return _lodgingFacilityIds;
}
// All ACTIVE facilities Ids
function getActiveLodgingFacilityIds() public view override returns (bytes32[] memory activeLodgingFacilityIds) {
activeLodgingFacilityIds = new bytes32[](_getActiveLodgingFacilitiesCount());
uint256 index;
for (uint256 i = 0; i < _lodgingFacilityIds.length; i++) {
if (lodgingFacilities[_lodgingFacilityIds[i]].active) {
activeLodgingFacilityIds[index] = _lodgingFacilityIds[i];
index++;
}
}
}
// All spaces Ids from facility by Id
function getSpaceIdsByFacilityId(bytes32 _lodgingFacilityId) public view override returns (bytes32[] memory) {
return _spaceIdsByFacilityId[_lodgingFacilityId];
}
// All ACTIVE spaces Ids from facility by Id
function getActiveSpaceIdsByFacilityId(bytes32 _lodgingFacilityId) public view override returns (bytes32[] memory activeSpacesIds) {
activeSpacesIds = new bytes32[](_getActiveSpacesCount(_lodgingFacilityId));
bytes32[] memory facilitiesSpaces = _spaceIdsByFacilityId[_lodgingFacilityId];
uint256 index;
for (uint256 i = 0; i < facilitiesSpaces.length; i++) {
if (spaces[facilitiesSpaces[i]].active) {
activeSpacesIds[index] = facilitiesSpaces[i];
index++;
}
}
}
// Availability of the space
function getAvailability(
bytes32 _spaceId,
uint256 _startDay,
uint256 _numberOfDays
) public view override returns (uint256[] memory) {
_checkBookingParams(_spaceId, _startDay, _numberOfDays);
Space memory _s = spaces[_spaceId];
uint256[] memory _availability = new uint256[](_numberOfDays);
for (uint256 _x = 0; _x < _numberOfDays; _x++) {
_availability[_x] = _s.capacity - _booked[_spaceId][_startDay + _x];
}
return _availability;
}
// Facilities by owner
function getLodgingFacilityIdsByOwner(address _owner) public view override returns (bytes32[] memory) {
return _facilityIdsByOwner[_owner];
}
// Facility details
function getLodgingFacilityById(bytes32 _lodgingFacilityId) public view override returns(
bool exists,
address owner,
bool active,
string memory dataURI
) {
LodgingFacility storage facility = lodgingFacilities[_lodgingFacilityId];
exists = facility.exists;
owner = facility.owner;
active = facility.active;
dataURI = facility.dataURI;
}
// Space details
function getSpaceById(bytes32 _spaceId) public view override returns (
bool exists,
bytes32 lodgingFacilityId,
uint256 capacity,
uint256 pricePerNightWei,
bool active,
string memory dataURI
) {
Space storage space = spaces[_spaceId];
exists = space.exists;
lodgingFacilityId = space.lodgingFacilityId;
capacity = space.capacity;
pricePerNightWei = space.pricePerNightWei;
active = space.active;
dataURI = space.dataURI;
}
// Returns a space details by Stay token Id
function getSpaceByTokenId(uint256 _tokenId) public view returns (
bool exists,
bytes32 lodgingFacilityId,
uint256 capacity,
uint256 pricePerNightWei,
bool active,
string memory dataURI
) {
return getSpaceById(_stays[_tokenId].spaceId);
}
// Get tokens Ids for a space filtered by a status
function getTokensBySpaceId(
bytes32 _spaceId,
State _state
) public view override returns (uint256[] memory) {
uint256[] storage _tokens = _stayTokens[_spaceId];
uint256 count;
for (uint256 i = 0; i < _tokens.length; i++) {
if (depositState(_tokens[i]) == _state) {
count++;
}
}
uint256[] memory _stateTokens = new uint256[](count);
uint256 index;
for (uint256 i = 0; i < _tokens.length; i++) {
if (depositState(_tokens[i]) == _state) {
_stateTokens[index] = _tokens[i];
index++;
}
}
return _stateTokens;
}
/*
* Lodging Facilities Management
*/
// Lodging Facility registration (with fren option)
function registerLodgingFacility(string calldata _dataURI, bool _active, address _fren) public override {
_dataUriMustBeProvided(_dataURI);
bytes32 _id = keccak256(
abi.encodePacked(
_msgSender(),
_dataURI
)
);
require(!lodgingFacilities[_id].exists, "Facility already exists");
lodgingFacilities[_id] = LodgingFacility(
_msgSender(),
_active,
true,
_dataURI,
_fren
);
_lodgingFacilityIds.push(_id);
_facilityIdsByOwner[_msgSender()].push(_id);
emit LodgingFacilityCreated(_id, _msgSender(), _dataURI);
}
// Lodging Facility registration (WITHOUT fren option)
function registerLodgingFacility(string calldata _dataURI, bool _active) public override {
return registerLodgingFacility(_dataURI, _active, address(0));
}
function updateLodgingFacility(bytes32 _lodgingFacilityId, string calldata _newDataURI) public override onlyLodgingFacilityOwner(_lodgingFacilityId) {
lodgingFacilities[_lodgingFacilityId].dataURI = _newDataURI;
emit LodgingFacilityUpdated(_lodgingFacilityId, _newDataURI);
}
function activateLodgingFacility(bytes32 _lodgingFacilityId) public override onlyLodgingFacilityOwner(_lodgingFacilityId) {
lodgingFacilities[_lodgingFacilityId].active = true;
emit LodgingFacilityActiveState(_lodgingFacilityId, true);
}
function deactivateLodgingFacility(bytes32 _lodgingFacilityId) public override onlyLodgingFacilityOwner(_lodgingFacilityId) {
lodgingFacilities[_lodgingFacilityId].active = false;
emit LodgingFacilityActiveState(_lodgingFacilityId, false);
}
function yieldLodgingFacility(bytes32 _lodgingFacilityId, address _newOwner) public override onlyLodgingFacilityOwner(_lodgingFacilityId) {
emit LodgingFacilityOwnershipTransfer(_lodgingFacilityId, lodgingFacilities[_lodgingFacilityId].owner, _newOwner);
lodgingFacilities[_lodgingFacilityId].owner = _newOwner;
}
function deleteLodgingFacility(bytes32 _lodgingFacilityId) public override onlyLodgingFacilityOwner(_lodgingFacilityId) {
lodgingFacilities[_lodgingFacilityId].exists = false;
emit LodgingFacilityRemoved(_lodgingFacilityId);
}
/*
* Spaces
*/
function addSpace(
bytes32 _lodgingFacilityId,
uint256 _capacity,
uint256 _pricePerNightWei,
bool _active,
string calldata _dataURI
) public override {
bytes32 _i = _lodgingFacilityId;
_facilityShouldExist(_i);
_shouldOnlyBeCalledByOwner(_i, "Only facility owner may add Spaces");
_dataUriMustBeProvided(_dataURI);
bytes32 _id = keccak256(abi.encodePacked(
_i,
_dataURI
));
require(!spaces[_id].exists, "Space already exists");
spaces[_id] = Space(
_i,
_capacity,
_pricePerNightWei,
_active,
true,
_dataURI
);
_spaceIdsByFacilityId[_i].push(_id);
emit SpaceAdded(_id, _i, _capacity, _pricePerNightWei, _active, _dataURI);
}
function updateSpace(
bytes32 _spaceId,
uint256 _capacity,
uint256 _pricePerNightWei,
bool _active,
string calldata _dataURI
) public override onlySpaceOwner(_spaceId) {
Space storage space = spaces[_spaceId];
emit SpaceAdded(
_spaceId,
space.lodgingFacilityId,
_capacity,
_pricePerNightWei,
_active,
_dataURI
);
}
function deleteSpace(bytes32 _spaceId) public override onlySpaceOwner(_spaceId) {
spaces[_spaceId].exists = false;
emit SpaceRemoved(_spaceId);
}
/**
* Stay escrow
*/
function deposit(
address payee,
bytes32 spaceId,
uint256 tokenId
) public payable override(IStayEscrow, StayEscrow) {
super.deposit(payee, spaceId, tokenId);
}
// Complete withdraw. Allowed in Checkout deposit state only
function withdraw(
address payer,
address payable payee,
bytes32 _spaceId,
uint256 tokenId
)
internal override(IStayEscrow, StayEscrow)
{
super.withdraw(payer, payee, _spaceId, tokenId);
}
// Partial withdraw
function withdraw(
address payer,
address payable payee,
uint256 payment,
bytes32 _spaceId,
uint256 tokenId
) internal override(IStayEscrow, StayEscrow) {
// partial withdraw condition
require(
payment <= spaces[_spaceId].pricePerNightWei,
"Withdraw amount not allows in this state"
);
super.withdraw(payer, payee, payment, _spaceId, tokenId);
}
/**
* Stays
*/
// // Returns a list of currently occupied spaces
// function getCurrentStayIdsByFacilityId(bytes32 _lodgingFacilityId)
// public view override returns (bytes32[] memory)
// {
// if (block.timestamp < dayZero) {
// return new bytes32[](0);
// }
// bytes32[] memory _activeSpacesIds =
// getActiveSpaceIdsByFacilityId(_lodgingFacilityId);
// uint256 currentDay = (block.timestamp - dayZero) / 86400;
// uint256 currentCount;
// Stay memory stay;
// for (uint256 i = 0; i < _activeSpacesIds.length; i++) {
// for (uint256 t=0; t < _stayTokens[_activeSpacesIds[i]].length; t++) {
// stay = _stays[_stayTokens[_activeSpacesIds[i]][t]];
// if (
// currentDay >= stay.startDay &&
// currentDay <= (stay.startDay + stay.numberOfDays)
// ) {
// currentCount++;
// }
// }
// }
// bytes32[] memory stayIds = new bytes32[](currentCount);
// uint256 index;
// for (uint256 i = 0; i < currentCount; i++) {
// for (uint256 t=0; t < _stayTokens[_activeSpacesIds[i]].length; t++) {
// stay = _stays[_stayTokens[_activeSpacesIds[i]][t]];
// if (
// currentDay >= stay.startDay &&
// currentDay <= (stay.startDay + stay.numberOfDays)
// ) {
// stayIds[index] = _activeSpacesIds[i];
// }
// }
// }
// return stayIds;
// }
// // Returns a list of booked spaces (except for checked in spaces)
// function getFutureStayIdsByFacilityId(bytes32 _lodgingFacilityId)
// public view override returns (bytes32[] memory)
// {
// if (block.timestamp < dayZero) {
// return new bytes32[](0);
// }
// bytes32[] memory _activeSpacesIds =
// getActiveSpaceIdsByFacilityId(_lodgingFacilityId);
// uint256 currentDay = (block.timestamp - dayZero) / 86400;
// uint256 futureCount;
// Stay memory stay;
// for (uint256 i = 0; i < _activeSpacesIds.length; i++) {
// for (uint256 t=0; t < _stayTokens[_activeSpacesIds[i]].length; t++) {
// stay = _stays[_stayTokens[_activeSpacesIds[i]][t]];
// if ((stay.startDay + stay.numberOfDays) > currentDay) {
// futureCount++;
// }
// }
// }
// bytes32[] memory stayIds = new bytes32[](futureCount);
// uint256 index;
// for (uint256 i = 0; i < futureCount; i++) {
// for (uint256 t=0; t < _stayTokens[_activeSpacesIds[i]].length; t++) {
// stay = _stays[_stayTokens[_activeSpacesIds[i]][t]];
// if ((stay.startDay + stay.numberOfDays) > currentDay) {
// stayIds[index] = _activeSpacesIds[i];
// }
// }
// }
// return stayIds;
// }
// Book a new stay in a space
function newStay(
bytes32 _spaceId,
uint256 _startDay,
uint256 _numberOfDays,
uint256 _quantity
) public payable override returns (uint256) {
_checkBookingParams(_spaceId, _startDay, _numberOfDays);
Space storage _s = spaces[_spaceId];
uint256 _stayPrice = _numberOfDays * _quantity * _s.pricePerNightWei;
require(msg.value >= _stayPrice, "Need. More. Money!");
for (uint256 _x = 0; _x < _numberOfDays; _x++) {
require(
_s.capacity - _booked[_spaceId][_startDay+_x] >= _quantity,
"Insufficient inventory"
);
_booked[_spaceId][_startDay+_x] += _quantity;
}
_stayTokenIds.increment();
uint256 _newStayTokenId = _stayTokenIds.current();
_safeMint(_msgSender(), _newStayTokenId);
// Inline tokenURI (data:application/json;base64)
string memory _tokenURI = StayTokenMeta.createTokenUri(
_newStayTokenId,
_s.lodgingFacilityId,
_spaceId,
_startDay,
_numberOfDays,
_quantity,
tokenImageURI,
serviceURI
);
_setTokenURI(_newStayTokenId, _tokenURI);
_stays[_newStayTokenId] = Stay(
_spaceId,
_startDay,
_numberOfDays,
_quantity,
false,
false
);
_stayTokens[_spaceId].push(_newStayTokenId);
deposit(_msgSender(), _spaceId, _newStayTokenId);
// @todo LIF/WIN
// @todo LodgingFacility loyalty token
// @todo divert all the excess WEI to Ukraine DAO
// @todo Receive Ukraine Supporter NFT
emit NewStay(_spaceId, _newStayTokenId);
return _newStayTokenId;
}
/**
* CheckIn
*/
// Stay checkIn; can be called by a stay token owner
function checkIn(
uint256 _tokenId,
CheckInVoucher memory voucher
) public override {
address recovered = _verifyCheckInVoucher(voucher);
Stay storage _stay = _stays[_tokenId];
bytes32 _spaceId = _stay.spaceId;
require(_spaceId != bytes32(0), "Stay not found");
require(!_stay.checkIn, "Already checked in");
Space storage _space = spaces[_spaceId];
LodgingFacility storage _lodgingFacility = lodgingFacilities[_space.lodgingFacilityId];
require(
recovered == ownerOf(_tokenId) || recovered == _lodgingFacility.owner,
"Voucher signer is not allowed"
);
require(
_msgSender() == voucher.to,
"Wrong caller"
);
uint256 firstNight = _space.pricePerNightWei;
// Partial withdraw, just for a first night
_stay.checkIn = true;
withdraw(
ownerOf(_tokenId),
payable(_lodgingFacility.owner),
firstNight,
_spaceId,
_tokenId
);
emit CheckIn(_tokenId);
}
/**
* CheckOut
*/
function checkOut(uint256 _tokenId) public virtual override {
Stay storage _stay = _stays[_tokenId];
require(_stay.spaceId != bytes32(0), "Stay not found");
require(!_stay.checkOut, "Already checked out");
bytes32 _spaceId = _stay.spaceId;
address spaceOwner = lodgingFacilities[spaces[_spaceId].lodgingFacilityId].owner;
require(
_msgSender() == spaceOwner,
"Only space owner is allowed"
);
// CheckOut condition by time
require(
block.timestamp >= dayZero + (_stay.startDay + _stay.numberOfDays) * 86400,
"Forbidden unless checkout date"
);
// Complete withdraw (rest of deposit)
_stay.checkOut = true;
withdraw(
ownerOf(_tokenId),
payable(spaceOwner),
_spaceId,
_tokenId
);
emit CheckOut(_tokenId);
}
// Makes stay cancellation
function cancel(uint256 _tokenId) public override onlyTokenOwner(_tokenId) {
refund(payable(ownerOf(_tokenId)), _stays[_tokenId].spaceId, _tokenId);
_burn(_tokenId);
emit Cancel(_tokenId);
}
/*
* Helpers
*/
function _facilityShouldExist(bytes32 _i) internal view {
require(lodgingFacilities[_i].exists, "Facility does not exist");
}
function _spaceShouldExist(bytes32 _i) internal view {
require(spaces[_i].exists, "Space does not exist");
}
function _shouldOnlyBeCalledByOwner(bytes32 _i, string memory _message) internal view {
require(lodgingFacilities[_i].owner == _msgSender(), _message);
}
function _dataUriMustBeProvided(string memory _uri) internal pure {
require(bytes(_uri).length > 0, "Data URI must be provided");
}
function _checkBookingParams(bytes32 _spaceId, uint256 _startDay, uint256 _numberOfDays) internal view {
require(dayZero + _startDay * 86400 > block.timestamp - 86400 * 2, "Don't stay in the past");
require(lodgingFacilities[spaces[_spaceId].lodgingFacilityId].active, "Lodging Facility is inactive");
require(spaces[_spaceId].active, "Space is inactive");
require(_numberOfDays > 0, "Number of days should be 1 or more");
}
function _getActiveLodgingFacilitiesCount() internal view returns (uint256 count) {
for (uint256 i = 0; i < _lodgingFacilityIds.length; i++) {
if (lodgingFacilities[_lodgingFacilityIds[i]].active) {
count++;
}
}
}
function _getActiveSpacesCount(bytes32 _lodgingFacilityId) internal view returns (uint256 count) {
bytes32[] storage facilitiesSpaces = _spaceIdsByFacilityId[_lodgingFacilityId];
for (uint256 i = 0; i < facilitiesSpaces.length; i++) {
if (spaces[facilitiesSpaces[i]].active) {
count++;
}
}
}
// Throws an error if verification of a voucher is fails
function _verifyCheckInVoucher(CheckInVoucher memory voucher) internal view returns (address) {
bytes32 voucherHash = _hashTypedDataV4(
keccak256(
abi.encode(
keccak256("Voucher(address from,address to,uint256 tokenId)"),
voucher.from,
voucher.to,
voucher.tokenId
)
)
);
(address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(voucherHash, voucher.signature);
require(
error == ECDSA.RecoverError.NoError && recovered == voucher.from,
"Broken voucher"
);
return recovered;
}
/** Overrides */
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
@openzeppelin/contracts/token/ERC721/ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
@openzeppelin/contracts/token/ERC721/IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721URIStorage.sol)
pragma solidity ^0.8.0;
import "../ERC721.sol";
/**
* @dev ERC721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is ERC721 {
using Strings for uint256;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return super.tokenURI(tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
@openzeppelin/contracts/utils/Base64.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Base64.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides a set of functions to operate with Base64 strings.
*
* _Available since v4.5._
*/
library Base64 {
/**
* @dev Base64 Encoding/Decoding Table
*/
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/**
* @dev Converts a `bytes` to its Bytes64 `string` representation.
*/
function encode(bytes memory data) internal pure returns (string memory) {
/**
* Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
* https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
*/
if (data.length == 0) return "";
// Loads the table into memory
string memory table = _TABLE;
// Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
// and split into 4 numbers of 6 bits.
// The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
// - `data.length + 2` -> Round up
// - `/ 3` -> Number of 3-bytes chunks
// - `4 *` -> 4 characters for each chunk
string memory result = new string(4 * ((data.length + 2) / 3));
assembly {
// Prepare the lookup table (skip the first "length" byte)
let tablePtr := add(table, 1)
// Prepare result pointer, jump over length
let resultPtr := add(result, 32)
// Run over the input, 3 bytes at a time
for {
let dataPtr := data
let endPtr := add(data, mload(data))
} lt(dataPtr, endPtr) {
} {
// Advance 3 bytes
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
// To write each character, shift the 3 bytes (18 bits) chunk
// 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
// and apply logical AND with 0x3F which is the number of
// the previous character in the ASCII table prior to the Base64 Table
// The result is then added to the table to get the character to write,
// and finally write it in the result pointer but with a left shift
// of 256 (1 byte) - 8 (1 ASCII char) = 248 bits
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1) // Advance
}
// When data `bytes` is not exactly 3 bytes long
// it is padded with `=` characters at the end
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
return result;
}
}
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
@openzeppelin/contracts/utils/Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
pragma solidity ^0.8.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
@openzeppelin/contracts/utils/Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
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);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
@openzeppelin/contracts/utils/cryptography/ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)
pragma solidity ^0.8.0;
import "./ECDSA.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*/
abstract contract EIP712 {
/* solhint-disable var-name-mixedcase */
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
// invalidate the cached domain separator if the chain id changes.
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}
@openzeppelin/contracts/utils/introspection/ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
contracts/IStayEscrow.sol
// SPDX-License-Identifier: GPL
pragma solidity ^0.8.0;
abstract contract IStayEscrow {
enum State {
Checkin,
Checkout,
Closed
}
event Deposited(address indexed payee, uint256 weiAmount, bytes32 spaceId, uint256 tokenId);
event Withdraw(address indexed payer, address indexed payee, uint256 weiAmount, bytes32 spaceId, uint256 tokenId);
event Refund(address indexed payee, uint256 weiAmount, bytes32 spaceId, uint256 tokenId);
function depositOf(address payer, bytes32 spaceId, uint256 tokenId) public view virtual returns (uint256);
function depositState(uint256 tokenId) public view virtual returns (State);
function deposit(address payer, bytes32 spaceId, uint256 tokenId) public payable virtual;
// Complete withdraw - state "Checkout" only
function withdraw(
address payer,
address payable payee,
bytes32 spaceId,
uint256 tokenId
) internal virtual;
// Partial withdraw - state "Checkin"
function withdraw(
address payer,
address payable payee,
uint256 payment,
bytes32 spaceId,
uint256 tokenId
) internal virtual;
// Refund deposit
function refund(
address payable payee,
bytes32 spaceId,
uint256 tokenId
) internal virtual;
}
contracts/IStays.sol
// SPDX-License-Identifier: GPL
pragma solidity ^0.8.0;
import "./IStayEscrow.sol";
abstract contract IStays is IStayEscrow {
// Check-In voucher
struct CheckInVoucher {
address from;
address to;
uint256 tokenId;
bytes signature;
}
// Events
event LodgingFacilityCreated(bytes32 facilityId, address indexed owner, string dataURI);
event LodgingFacilityUpdated(bytes32 facilityId, string dataURI);
event LodgingFacilityActiveState(bytes32 facilityId, bool active);
event LodgingFacilityOwnershipTransfer(bytes32 facilityId, address indexed prevOwner, address indexed newOwner);
event LodgingFacilityRemoved(bytes32 facilityId);
event SpaceAdded(bytes32 spaceId, bytes32 facilityId, uint256 capacity, uint256 pricePerNightWei, bool active, string dataURI);
event SpaceUpdated(bytes32 spaceId, bytes32 facilityId, uint256 capacity, uint256 pricePerNightWei, bool active, string dataURI);
event SpaceRemoved(bytes32 spaceId);
event NewStay(bytes32 spaceId, uint256 tokenId);
event CheckIn(uint256 tokenId);
event CheckOut(uint256 tokenId);
event Cancel(uint256 tokenId);
// To display all availability in Glider: getActiveLodgingFacilityIds, getSpaceIdsByFacilityId, getAvailability
function getAllLodgingFacilityIds() public view virtual returns (bytes32[] memory);
function getActiveLodgingFacilityIds() public view virtual returns (bytes32[] memory);
function getSpaceIdsByFacilityId(bytes32 _lodgingFacilityId) public virtual returns (bytes32[] memory);
function getActiveSpaceIdsByFacilityId(bytes32 _lodgingFacilityId) public virtual returns (bytes32[] memory);
function getAvailability(bytes32 _spaceId, uint256 _startDay, uint256 _numberOfDays) public view virtual returns (uint256[] memory);
// For the lodging facility owner, to display their facilities
function getLodgingFacilityIdsByOwner(address _owner) public virtual returns (bytes32[] memory);
// Facility and spaces details
function getLodgingFacilityById(bytes32 _lodgingFacilityId) public view virtual returns(
bool exists,
address owner,
bool active,
string memory dataURI
);
function getSpaceById(bytes32 _spaceId) public view virtual returns (
bool exists,
bytes32 lodgingFacilityId,
uint256 capacity,
uint256 pricePerNightWei,
bool active,
string memory dataURI
);
// Tokens by spaces and status
function getTokensBySpaceId(bytes32 _spaceId, State _state) public view virtual returns (uint256[] memory);
// Facility management
function registerLodgingFacility(string calldata _dataURI, bool _active, address _fren) public virtual;
function registerLodgingFacility(string calldata _dataURI, bool _active) public virtual;
function updateLodgingFacility(bytes32 _lodgingFacilityId, string calldata _newDataURI) public virtual;
function activateLodgingFacility(bytes32 _lodgingFacilityId) public virtual;
function deactivateLodgingFacility(bytes32 _lodgingFacilityId) public virtual;
function yieldLodgingFacility(bytes32 _lodgingFacilityId, address _newOwner) public virtual;
function deleteLodgingFacility(bytes32 _lodgingFacilityId) public virtual;
// Space management
function addSpace(bytes32 _lodgingFacilityId, uint256 _capacity, uint256 _pricePerNightWei, bool _active, string calldata _dataURI) public virtual;
function updateSpace(bytes32 _spaceId, uint256 _capacity, uint256 _pricePerNightWei, bool _active, string calldata _dataURI) public virtual;
function deleteSpace(bytes32 _spaceId) public virtual;
// Delegates (addresses that can perform certain actions, like check-in and check-out)
// function addDelegate(bytes32 _lodgingFacilityId, address _delegate, uint8 _accessLevel) public virtual;
// function changeDelegateAccessLevel(bytes32 _lodgingFacilityId, address _delegate, uint8 _accessLevel) public virtual;
// function removeDelegate(bytes32 _lodgingFacilityId, address _delegate) public virtual;
// Stays
function newStay(bytes32 _spaceId, uint256 _startDay, uint256 _numberOfDays, uint256 _quantity) public payable virtual returns (uint256);
// getting all my Stays is via built-in NFT contract getter
// getting Stay details is via NFT's tokenURI getter
// function getAllStayIdsByFacilityId(bytes32 _lodgingFacilityId) public virtual returns (uint256[] memory);
// function getCurrentStayIdsByFacilityId(bytes32 _lodgingFacilityId) public virtual returns (bytes32[] memory);
// function getFutureStayIdsByFacilityId(bytes32 _lodgingFacilityId) public virtual returns (bytes32[] memory);
function checkIn(uint256 _tokenId, CheckInVoucher memory voucher) public virtual;
function checkOut(uint256 _tokenId) public virtual;
function cancel(uint256 _tokenId) public virtual;
// function requestChange(uint256 _tokenId, bytes32 _spaceId, uint256 _startDay, uint256 _numberOfDays, uint256 _quantity) public payable virtual;
// function requestCancel(int256 _tokenId) public virtual;
// function requestResponse(uint256 _tokenId, bool _answer) public virtual;
// @todo change my contact information
// Reviews
// @todo leave a LF review
// @todo leave a Guest review
// @todo answer a review
// @todo start a dispute on a review
}
contracts/StayEscrow.sol
// SPDX-License-Identifier: GPL
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Address.sol";
import "./IStayEscrow.sol";
import "hardhat/console.sol";
abstract contract StayEscrow is IStayEscrow {
using Address for address payable;
// spaceId => payer address => tokenId => deposit
mapping(bytes32 => mapping (address => mapping(uint256 => uint256))) private _deposits;
// tokenId => State
mapping(uint256 => State) private _states;
function depositOf(address payer, bytes32 spaceId, uint256 tokenId) public view override(IStayEscrow) virtual returns (uint256) {
return _deposits[spaceId][payer][tokenId];
}
function depositState(uint256 tokenId) public view override(IStayEscrow) virtual returns (State) {
return _states[tokenId];
}
function deposit(address payer, bytes32 spaceId, uint256 tokenId) public payable override(IStayEscrow) virtual {
uint256 amount = msg.value;
_deposits[spaceId][payer][tokenId] += amount;
_states[tokenId] = State.Checkin;
emit Deposited(payer, amount, spaceId, tokenId);
}
// Complete withdraw - state "Checkout" only
function withdraw(
address payer,
address payable payee,
bytes32 spaceId,
uint256 tokenId
) internal override(IStayEscrow) virtual {
uint256 payment = _deposits[spaceId][payer][tokenId];
require(payment >= 0, "Insufficient funds");
require(
_states[tokenId] == State.Checkout,
"Complete withdraw not allowed in this state"
);
_deposits[spaceId][payer][tokenId] = 0;
_states[tokenId] = State.Closed;
if (payment > 0) {
payee.sendValue(payment);
emit Withdraw(payer, payee, payment, spaceId, tokenId);
}
}
// Partial withdraw - state "Checkin"
function withdraw(
address payer,
address payable payee,
uint256 payment,
bytes32 spaceId,
uint256 tokenId
) internal override(IStayEscrow) virtual {
require(payment <= _deposits[spaceId][payer][tokenId], "Insufficient funds");
_deposits[spaceId][payer][tokenId] = _deposits[spaceId][payer][tokenId] - payment;
_states[tokenId] = State.Checkout;
payee.sendValue(payment);
emit Withdraw(payer, payee, payment, spaceId, tokenId);
}
// Refund deposit
function refund(
address payable payee,
bytes32 spaceId,
uint256 tokenId
) internal override(IStayEscrow) virtual {
require(
_states[tokenId] == State.Checkin,
"Refund not allowed in current state"
);
require(_deposits[spaceId][payee][tokenId] > 0, "Insufficient funds");
uint256 payment = _deposits[spaceId][payee][tokenId];
_deposits[spaceId][payee][tokenId] = 0;
_states[tokenId] = State.Closed;
payee.sendValue(payment);
emit Refund(payee, payment, spaceId, tokenId);
}
}
contracts/libraries/StayTokenMeta.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Base64.sol";
library StayTokenMeta {
function createTokenUri(
uint256 tokenId,
bytes32 facilityId,
bytes32 spaceId,
uint256 startDay,
uint256 numberOfDays,
uint256 quantity,
string memory tokenImageURI,
string memory serviceURI
) internal pure returns (string memory) {
// Creation of data URI is split up into several functions because of
// variables stack number restriction in Solidity
return createDataUri(
string(
abi.encodePacked(
'{',
createMandatoryProps(tokenId, tokenImageURI, serviceURI, spaceId),
',',
createAttributesProps(facilityId, spaceId, startDay, numberOfDays, quantity),
'}'
)
)
);
}
function createMandatoryProps(
uint256 tokenId,
string memory tokenImageURI,
string memory serviceURI,
bytes32 spaceId
) internal pure returns (string memory) {
return string(
abi.encodePacked(
'"name":"StayToken #',
uintToString(tokenId),
'","description":"Stay at lodging facility","image":"',
tokenImageURI,
'","external_url":"',
serviceURI,
'space/',
toHex(spaceId),
'"'
)
);
}
function createAttributesProps(
bytes32 facilityId,
bytes32 spaceId,
uint256 startDay,
uint256 numberOfDays,
uint256 quantity
) internal pure returns (string memory) {
return string(
abi.encodePacked(
'"attributes":[{"trait_type":"facilityId","value":"',
toHex(facilityId),
'"},{"trait_type":"spaceId","value":"',
toHex(spaceId),
'"},{"trait_type":"startDay","value":"',
uintToString(startDay),
'"},{"trait_type":"numberOfDays","value":"',
uintToString(numberOfDays),
'"},{"trait_type":"quantity","value":"',
uintToString(quantity),
'"}]'
)
);
}
function createDataUri(string memory json) internal pure returns (string memory) {
return string(
abi.encodePacked(
'data:application/json;base64,',
Base64.encode(bytes(json))
)
);
}
function uintToString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT license
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
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);
}
function toHex16 (bytes16 data) internal pure returns (bytes32 result) {
result = bytes32 (data) & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 |
(bytes32 (data) & 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000) >> 64;
result = result & 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000 |
(result & 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000) >> 32;
result = result & 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000 |
(result & 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000) >> 16;
result = result & 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000 |
(result & 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000) >> 8;
result = (result & 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000) >> 4 |
(result & 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00) >> 8;
result = bytes32 (0x3030303030303030303030303030303030303030303030303030303030303030 +
uint256 (result) +
(uint256 (result) + 0x0606060606060606060606060606060606060606060606060606060606060606 >> 4 &
0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F) * 7);
}
function toHex(bytes32 data) internal pure returns (string memory) {
return string(
abi.encodePacked(
"0x",
toHex16(bytes16(data)), toHex16(bytes16 (data << 128))
)
);
}
}
hardhat/console.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
}
function logUint(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
}
function log(uint p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
}
function log(uint p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
}
function log(uint p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
}
function log(string memory p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
}
function log(uint p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
}
function log(uint p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
}
function log(uint p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
}
function log(uint p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
}
function log(uint p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
}
function log(uint p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
}
function log(uint p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
}
function log(uint p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
}
function log(uint p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
}
function log(uint p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
}
function log(uint p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
}
function log(uint p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
}
function log(uint p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
}
function log(uint p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
}
function log(uint p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
}
function log(string memory p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
}
function log(string memory p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
}
function log(string memory p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
}
function log(string memory p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
}
function log(bool p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
}
function log(bool p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
}
function log(bool p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
}
function log(address p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
}
function log(address p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
}
function log(address p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"approved","internalType":"address","indexed":true},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"ApprovalForAll","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"operator","internalType":"address","indexed":true},{"type":"bool","name":"approved","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"Cancel","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CheckIn","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"CheckOut","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Deposited","inputs":[{"type":"address","name":"payee","internalType":"address","indexed":true},{"type":"uint256","name":"weiAmount","internalType":"uint256","indexed":false},{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LodgingFacilityActiveState","inputs":[{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false},{"type":"bool","name":"active","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"LodgingFacilityCreated","inputs":[{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false},{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"string","name":"dataURI","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"LodgingFacilityOwnershipTransfer","inputs":[{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false},{"type":"address","name":"prevOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"LodgingFacilityRemoved","inputs":[{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"LodgingFacilityUpdated","inputs":[{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false},{"type":"string","name":"dataURI","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"NewStay","inputs":[{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Refund","inputs":[{"type":"address","name":"payee","internalType":"address","indexed":true},{"type":"uint256","name":"weiAmount","internalType":"uint256","indexed":false},{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SpaceAdded","inputs":[{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"capacity","internalType":"uint256","indexed":false},{"type":"uint256","name":"pricePerNightWei","internalType":"uint256","indexed":false},{"type":"bool","name":"active","internalType":"bool","indexed":false},{"type":"string","name":"dataURI","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"SpaceRemoved","inputs":[{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"SpaceUpdated","inputs":[{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"facilityId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"capacity","internalType":"uint256","indexed":false},{"type":"uint256","name":"pricePerNightWei","internalType":"uint256","indexed":false},{"type":"bool","name":"active","internalType":"bool","indexed":false},{"type":"string","name":"dataURI","internalType":"string","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":"Withdraw","inputs":[{"type":"address","name":"payer","internalType":"address","indexed":true},{"type":"address","name":"payee","internalType":"address","indexed":true},{"type":"uint256","name":"weiAmount","internalType":"uint256","indexed":false},{"type":"bytes32","name":"spaceId","internalType":"bytes32","indexed":false},{"type":"uint256","name":"tokenId","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"activateLodgingFacility","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addSpace","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"},{"type":"uint256","name":"_capacity","internalType":"uint256"},{"type":"uint256","name":"_pricePerNightWei","internalType":"uint256"},{"type":"bool","name":"_active","internalType":"bool"},{"type":"string","name":"_dataURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approve","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"cancel","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"checkIn","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"tuple","name":"voucher","internalType":"struct IStays.CheckInVoucher","components":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"bytes","name":"signature","internalType":"bytes"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"checkOut","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"dayZero","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deactivateLodgingFacility","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteLodgingFacility","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deleteSpace","inputs":[{"type":"bytes32","name":"_spaceId","internalType":"bytes32"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"deposit","inputs":[{"type":"address","name":"payee","internalType":"address"},{"type":"bytes32","name":"spaceId","internalType":"bytes32"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"depositOf","inputs":[{"type":"address","name":"payer","internalType":"address"},{"type":"bytes32","name":"spaceId","internalType":"bytes32"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"enum IStayEscrow.State"}],"name":"depositState","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"activeLodgingFacilityIds","internalType":"bytes32[]"}],"name":"getActiveLodgingFacilityIds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"activeSpacesIds","internalType":"bytes32[]"}],"name":"getActiveSpaceIdsByFacilityId","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getAllLodgingFacilityIds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getApproved","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getAvailability","inputs":[{"type":"bytes32","name":"_spaceId","internalType":"bytes32"},{"type":"uint256","name":"_startDay","internalType":"uint256"},{"type":"uint256","name":"_numberOfDays","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"exists","internalType":"bool"},{"type":"address","name":"owner","internalType":"address"},{"type":"bool","name":"active","internalType":"bool"},{"type":"string","name":"dataURI","internalType":"string"}],"name":"getLodgingFacilityById","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getLodgingFacilityIdsByOwner","inputs":[{"type":"address","name":"_owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"exists","internalType":"bool"},{"type":"bytes32","name":"lodgingFacilityId","internalType":"bytes32"},{"type":"uint256","name":"capacity","internalType":"uint256"},{"type":"uint256","name":"pricePerNightWei","internalType":"uint256"},{"type":"bool","name":"active","internalType":"bool"},{"type":"string","name":"dataURI","internalType":"string"}],"name":"getSpaceById","inputs":[{"type":"bytes32","name":"_spaceId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"exists","internalType":"bool"},{"type":"bytes32","name":"lodgingFacilityId","internalType":"bytes32"},{"type":"uint256","name":"capacity","internalType":"uint256"},{"type":"uint256","name":"pricePerNightWei","internalType":"uint256"},{"type":"bool","name":"active","internalType":"bool"},{"type":"string","name":"dataURI","internalType":"string"}],"name":"getSpaceByTokenId","inputs":[{"type":"uint256","name":"_tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32[]","name":"","internalType":"bytes32[]"}],"name":"getSpaceIdsByFacilityId","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"getTokensBySpaceId","inputs":[{"type":"bytes32","name":"_spaceId","internalType":"bytes32"},{"type":"uint8","name":"_state","internalType":"enum IStayEscrow.State"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isApprovedForAll","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"operator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"bool","name":"active","internalType":"bool"},{"type":"bool","name":"exists","internalType":"bool"},{"type":"string","name":"dataURI","internalType":"string"},{"type":"address","name":"fren","internalType":"address"}],"name":"lodgingFacilities","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"lodgingFacilitySchemaURI","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"newStay","inputs":[{"type":"bytes32","name":"_spaceId","internalType":"bytes32"},{"type":"uint256","name":"_startDay","internalType":"uint256"},{"type":"uint256","name":"_numberOfDays","internalType":"uint256"},{"type":"uint256","name":"_quantity","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ownerOf","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"registerLodgingFacility","inputs":[{"type":"string","name":"_dataURI","internalType":"string"},{"type":"bool","name":"_active","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"registerLodgingFacility","inputs":[{"type":"string","name":"_dataURI","internalType":"string"},{"type":"bool","name":"_active","internalType":"bool"},{"type":"address","name":"_fren","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"safeTransferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"serviceURI","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setApprovalForAll","inputs":[{"type":"address","name":"operator","internalType":"address"},{"type":"bool","name":"approved","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"spaceSchemaURI","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"lodgingFacilityId","internalType":"bytes32"},{"type":"uint256","name":"capacity","internalType":"uint256"},{"type":"uint256","name":"pricePerNightWei","internalType":"uint256"},{"type":"bool","name":"active","internalType":"bool"},{"type":"bool","name":"exists","internalType":"bool"},{"type":"string","name":"dataURI","internalType":"string"}],"name":"spaces","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"staySchemaURI","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenByIndex","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenOfOwnerByIndex","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"tokenURI","inputs":[{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"tokenId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateLodgingFacility","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"},{"type":"string","name":"_newDataURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateSpace","inputs":[{"type":"bytes32","name":"_spaceId","internalType":"bytes32"},{"type":"uint256","name":"_capacity","internalType":"uint256"},{"type":"uint256","name":"_pricePerNightWei","internalType":"uint256"},{"type":"bool","name":"_active","internalType":"bool"},{"type":"string","name":"_dataURI","internalType":"string"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"yieldLodgingFacility","inputs":[{"type":"bytes32","name":"_lodgingFacilityId","internalType":"bytes32"},{"type":"address","name":"_newOwner","internalType":"address"}]}]
Contract Creation Code
0x6101406040523480156200001257600080fd5b5060405180604001604052806005815260200164537461797360d81b815250604051806040016040528060018152602001603160f81b8152506040518060400160405280600981526020016829ba30bcaa37b5b2b760b91b8152506040518060400160405280600481526020016329aa191960e11b8152508160029080519060200190620000a292919062000156565b508051620000b890600390602084019062000156565b5050825160208085019190912083518483012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c0019052805194019390932091935091906080523060601b60c05261012052506200023992505050565b8280546200016490620001fc565b90600052602060002090601f016020900481019282620001885760008555620001d3565b82601f10620001a357805160ff1916838001178555620001d3565b82800160010185558215620001d3579182015b82811115620001d3578251825591602001919060010190620001b6565b50620001e1929150620001e5565b5090565b5b80821115620001e15760008155600101620001e6565b600181811c908216806200021157607f821691505b602082108114156200023357634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160601c60e0516101005161012051615ba36200028c600039600061460d0152600061465c0152600061463701526000614590015260006145ba015260006145e40152615ba36000f3fe6080604052600436106102c75760003560e01c80636a22dd2611610175578063c87b56dd116100dc578063e6ccb4ce11610095578063eb2243f81161006f578063eb2243f814610933578063f7cdbc9d14610946578063ffae741514610966578063ffc1e09a1461099757600080fd5b8063e6ccb4ce14610898578063e985e9c5146108b8578063e994529e1461090157600080fd5b8063c87b56dd146107f5578063cad302e414610815578063cf63247e146105ab578063d0470d7c14610858578063e1e33b9c14610878578063e3aae3a5146105ab57600080fd5b80639ff682141161012e5780639ff6821414610733578063a22cb46514610760578063a468803214610780578063b38759fd146107a0578063b88d4fde146107b5578063bfef4d40146107d557600080fd5b80636a22dd261461067e57806370a082311461069e57806380d288f2146106be5780638f201f5f146106de5780639518f5fa146106fe57806395d89b411461071e57600080fd5b806323b872dd11610234578063438c9cab116101ed5780634f6ccce7116101c75780634f6ccce7146105fe5780635ee7aa131461061e5780636352211e1461063e578063673f0dd51461065e57600080fd5b8063438c9cab1461058b578063462ef5ed146105ab5780634c18a8ec146105ce57600080fd5b806323b872dd146104b957806327d7cedb146104d95780632f745c59146104f9578063342df9b21461051957806340e58ee51461054b57806342842e0e1461056b57600080fd5b8063095ea7b311610286578063095ea7b3146103e057806318160ddd146104005780631b9bdb121461041f5780631bd2eeee146104665780631bf7509b1461048657806320bf6ddb146104a657600080fd5b8062442536146102cc578062d34b54146102ee57806301ffc9a714610319578063038c89751461034957806306fdde0314610386578063081812fc146103a8575b600080fd5b3480156102d857600080fd5b506102ec6102e7366004614ec2565b6109b7565b005b3480156102fa57600080fd5b50610303610a59565b604051610310919061568f565b60405180910390f35b34801561032557600080fd5b5061033961033436600461504b565b610b5a565b6040519015158152602001610310565b34801561035557600080fd5b50610379610364366004614ec2565b60009081526001602052604090205460ff1690565b60405161031091906157bc565b34801561039257600080fd5b5061039b610b6b565b60405161031091906157e4565b3480156103b457600080fd5b506103c86103c3366004614ec2565b610bfd565b6040516001600160a01b039091168152602001610310565b3480156103ec57600080fd5b506102ec6103fb366004614e98565b610c85565b34801561040c57600080fd5b50600b545b604051908152602001610310565b34801561042b57600080fd5b5061041161043a366004614e65565b6000918252602082815260408084206001600160a01b0395909516845293815283832091835252205490565b34801561047257600080fd5b506102ec610481366004614ec2565b610d9b565b34801561049257600080fd5b506103036104a1366004614d4a565b610f5b565b6104116104b4366004615019565b610fc7565b3480156104c557600080fd5b506102ec6104d4366004614d98565b6112a5565b3480156104e557600080fd5b506103036104f4366004614f7d565b6112d6565b34801561050557600080fd5b50610411610514366004614e98565b611491565b34801561052557600080fd5b50610539610534366004614ec2565b611527565b604051610310969594939291906156fb565b34801561055757600080fd5b506102ec610566366004614ec2565b6115f6565b34801561057757600080fd5b506102ec610586366004614d98565b6116ba565b34801561059757600080fd5b506102ec6105a6366004614f32565b6116d5565b3480156105b757600080fd5b5061039b6040518060200160405280600081525081565b3480156105da57600080fd5b506105ee6105e9366004614ec2565b611766565b60405161031094939291906156c7565b34801561060a57600080fd5b50610411610619366004614ec2565b611832565b34801561062a57600080fd5b506102ec610639366004614fa9565b6118c5565b34801561064a57600080fd5b506103c8610659366004614ec2565b611b09565b34801561066a57600080fd5b50610539610679366004614ec2565b611b80565b34801561068a57600080fd5b506102ec610699366004614ec2565b611bb7565b3480156106aa57600080fd5b506104116106b9366004614d4a565b611c43565b3480156106ca57600080fd5b506102ec6106d9366004614fa9565b611cca565b3480156106ea57600080fd5b506102ec6106f9366004614edb565b611d65565b34801561070a57600080fd5b50610303610719366004614ec2565b611e26565b34801561072a57600080fd5b5061039b611e86565b34801561073f57600080fd5b5061074b6362155d6e81565b60405163ffffffff9091168152602001610310565b34801561076c57600080fd5b506102ec61077b366004614e3b565b611e95565b34801561078c57600080fd5b506102ec61079b366004614ec2565b611ea4565b3480156107ac57600080fd5b50610303611f42565b3480156107c157600080fd5b506102ec6107d0366004614dd4565b611f99565b3480156107e157600080fd5b506103036107f0366004614efe565b611fd1565b34801561080157600080fd5b5061039b610810366004614ec2565b612163565b34801561082157600080fd5b5061039b6040518060400160405280601781526020017668747470733a2f2f6c6f63616c686f73743a333030302f60481b81525081565b34801561086457600080fd5b506102ec610873366004614ec2565b61216e565b34801561088457600080fd5b506102ec610893366004615085565b612208565b3480156108a457600080fd5b506102ec6108b336600461513c565b612215565b3480156108c457600080fd5b506103396108d3366004614d65565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b34801561090d57600080fd5b5061092161091c366004614ec2565b612410565b60405161031096959493929190615787565b6102ec610941366004614e65565b6124d8565b34801561095257600080fd5b506102ec6109613660046150d8565b6124e3565b34801561097257600080fd5b50610986610981366004614ec2565b612759565b604051610310959493929190615648565b3480156109a357600080fd5b506103036109b2366004614ec2565b61282c565b60008181526010602052604090205481906001600160a01b0316336001600160a01b031614610a015760405162461bcd60e51b81526004016109f890615849565b60405180910390fd5b6000828152601060209081526040808320805460ff60a01b191690558051858152918201929092527f5c33859dfe8722791b5d72ad942a0895181f8a694288ec429394f620de15032091015b60405180910390a15050565b6060610a63612984565b6001600160401b03811115610a7a57610a7a615a7d565b604051908082528060200260200182016040528015610aa3578160200160208202803683370190505b5090506000805b600e54811015610b555760106000600e8381548110610acb57610acb615a67565b9060005260206000200154815260200190815260200160002060000160149054906101000a900460ff1615610b4357600e8181548110610b0d57610b0d615a67565b9060005260206000200154838381518110610b2a57610b2a615a67565b602090810291909101015281610b3f816159e0565b9250505b80610b4d816159e0565b915050610aaa565b505090565b6000610b65826129fc565b92915050565b606060028054610b7a906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ba6906159a5565b8015610bf35780601f10610bc857610100808354040283529160200191610bf3565b820191906000526020600020905b815481529060010190602001808311610bd657829003601f168201915b5050505050905090565b6000610c0882612a21565b610c695760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016109f8565b506000908152600660205260409020546001600160a01b031690565b6000610c9082611b09565b9050806001600160a01b0316836001600160a01b03161415610cfe5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084016109f8565b336001600160a01b0382161480610d1a5750610d1a81336108d3565b610d8c5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016109f8565b610d968383612a3e565b505050565b60008181526014602052604090208054610de85760405162461bcd60e51b815260206004820152600e60248201526d14dd185e481b9bdd08199bdd5b9960921b60448201526064016109f8565b6004810154610100900460ff1615610e385760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e4818da1958dad959081bdd5d606a1b60448201526064016109f8565b8054600081815260126020908152604080832054835260109091529020546001600160a01b0316338114610e7e5760405162461bcd60e51b81526004016109f89061588f565b82600201548360010154610e929190615917565b610e9f9062015180615943565b610ead906362155d6e615917565b421015610efc5760405162461bcd60e51b815260206004820152601e60248201527f466f7262696464656e20756e6c65737320636865636b6f75742064617465000060448201526064016109f8565b60048301805461ff001916610100179055610f21610f1985611b09565b828487612aac565b6040518481527f2c276699fefbad45f18509233bc03bb9cfdf41b18f32756933188bdef35fef55906020015b60405180910390a150505050565b6001600160a01b0381166000908152600f6020908152604091829020805483518184028101840190945280845260609392830182828015610fbb57602002820191906000526020600020905b815481526020019060010190808311610fa7575b50505050509050919050565b6000610fd4858585612ab8565b60008581526012602052604081206002810154909190610ff48587615943565b610ffe9190615943565b9050803410156110455760405162461bcd60e51b81526020600482015260126024820152714e6565642e204d6f72652e204d6f6e65792160701b60448201526064016109f8565b60005b8581101561111e576000888152601360205260408120869161106a848b615917565b81526020019081526020016000205484600101546110889190615962565b10156110cf5760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420696e76656e746f727960501b60448201526064016109f8565b600088815260136020526040812086916110e9848b615917565b815260200190815260200160002060008282546111069190615917565b90915550819050611116816159e0565b915050611048565b5061112d600d80546001019055565b6000611138600d5490565b90506111443382612c48565b60006111a18285600001548b8b8b8b6040518060a0016040528060628152602001615b0c606291396040518060400160405280601781526020017668747470733a2f2f6c6f63616c686f73743a333030302f60481b815250612c62565b90506111ad8282612cb2565b6040805160c0810182528a815260208082018b81528284018b8152606084018b815260006080860181815260a087018281528a8352601487528883209751885594516001888101919091559351600288015591516003870155905160049095018054935115156101000261ff00199615159690961661ffff1990941693909317949094179091558c83526015825292822080549384018155825290200182905561125e6112573390565b8a846124d8565b604080518a8152602081018490527fe04083eb622e3cb7d063f319076c83270c24acb409a3bc13abcfb36af60f8617910160405180910390a150925050505b949350505050565b6112af3382612d3d565b6112cb5760405162461bcd60e51b81526004016109f8906158c6565b610d96838383612e23565b60606112e3848484612ab8565b6000848152601260209081526040808320815160c08101835281548152600182015493810193909352600281015491830191909152600381015460ff80821615156060850152610100909104161515608083015260048101805460a08401919061134c906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054611378906159a5565b80156113c55780601f1061139a576101008083540402835291602001916113c5565b820191906000526020600020905b8154815290600101906020018083116113a857829003601f168201915b50505050508152505090506000836001600160401b038111156113ea576113ea615a7d565b604051908082528060200260200182016040528015611413578160200160208202803683370190505b50905060005b848110156114875760008781526013602052604081209061143a8389615917565b81526020019081526020016000205483602001516114589190615962565b82828151811061146a5761146a615a67565b60209081029190910101528061147f816159e0565b915050611419565b5095945050505050565b600061149c83611c43565b82106114fe5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016109f8565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6000818152601260205260409020600381015481546001830154600284015460048501805460ff61010087048116979596949593941692606092909161156c906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054611598906159a5565b80156115e55780601f106115ba576101008083540402835291602001916115e5565b820191906000526020600020905b8154815290600101906020018083116115c857829003601f168201915b505050505091505091939550919395565b8061160081611b09565b6001600160a01b0316336001600160a01b0316146116605760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79207374617920746f6b656e206f776e657220697320616c6c6f77656460448201526064016109f8565b61168161166c83611b09565b60008481526014602052604090205484612fca565b61168a82613150565b6040518281527f8bf30e7ff26833413be5f69e1d373744864d600b664204b4a2f9844a8eedb9ed90602001610a4d565b610d9683838360405180602001604052806000815250611f99565b60008381526010602052604090205483906001600160a01b0316336001600160a01b0316146117165760405162461bcd60e51b81526004016109f890615849565b6000848152601060205260409020611732906001018484614b12565b507fb252d91e8d424ba6f9f1647d21d7b0bbd8e2a3cbb318aaecb0d735fba9f62c7f848484604051610f4d93929190615764565b6000818152601060205260409020805460018201805460ff600160a81b84048116946001600160a01b03851694600160a01b9004909116926060926117aa906159a5565b80601f01602080910402602001604051908101604052809291908181526020018280546117d6906159a5565b80156118235780601f106117f857610100808354040283529160200191611823565b820191906000526020600020905b81548152906001019060200180831161180657829003601f168201915b50505050509150509193509193565b600061183d600b5490565b82106118a05760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016109f8565b600b82815481106118b3576118b3615a67565b90600052602060002001549050919050565b856118cf8161315c565b6118f181604051806060016040528060228152602001615aaa602291396131c1565b61193083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131fa92505050565b600081848460405160200161194793929190615293565b60408051808303601f19018152918152815160209283012060008181526012909352912060030154909150610100900460ff16156119be5760405162461bcd60e51b8152602060048201526014602482015273537061636520616c72656164792065786973747360601b60448201526064016109f8565b6040518060c00160405280838152602001888152602001878152602001861515815260200160011515815260200185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093909452505083815260126020908152604091829020845181558482015160018201559184015160028301556060840151600383018054608087015115156101000261ff00199315159390931661ffff199091161791909117905560a08401518051929350611a969260048501929190910190614b92565b505050600082815260116020908152604080832080546001810182559084529190922001829055517f335958c15e70938d2bfae6c90457d7732a3e398f2423c491dc6503b67334745a90611af790839085908b908b908b908b908b90615730565b60405180910390a15050505050505050565b6000818152600460205260408120546001600160a01b031680610b655760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b60648201526084016109f8565b6000818152601460205260408120548190819081908190606090611ba390611527565b949c939b5091995097509550909350915050565b60008181526010602052604090205481906001600160a01b0316336001600160a01b031614611bf85760405162461bcd60e51b81526004016109f890615849565b60008281526010602052604090819020805460ff60a81b19169055517f9cb52f05776b0f321eb9ca8c9e1b26b978036072417bf384bd406189f43864f890610a4d9084815260200190565b60006001600160a01b038216611cae5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016109f8565b506001600160a01b031660009081526005602052604090205490565b6000868152601260209081526040808320548352601090915290205486906001600160a01b0316336001600160a01b031614611d185760405162461bcd60e51b81526004016109f89061588f565b600087815260126020526040908190208054915190917f335958c15e70938d2bfae6c90457d7732a3e398f2423c491dc6503b67334745a91611af7918b918b908b908b908b908b90615730565b60008281526010602052604090205482906001600160a01b0316336001600160a01b031614611da65760405162461bcd60e51b81526004016109f890615849565b6000838152601060209081526040918290205491518581526001600160a01b038581169316917f11a520c5c4bfade8b450399ea67096dba36478d23d9a45f02e32989cfe307dde910160405180910390a35060009182526010602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b600081815260116020908152604091829020805483518184028101840190945280845260609392830182828015610fbb5760200282019190600052602060002090815481526020019060010190808311610fa75750505050509050919050565b606060038054610b7a906159a5565b611ea033838361324b565b5050565b60008181526010602052604090205481906001600160a01b0316336001600160a01b031614611ee55760405162461bcd60e51b81526004016109f890615849565b60008281526010602052604090819020805460ff60a01b1916600160a01b179055517f5c33859dfe8722791b5d72ad942a0895181f8a694288ec429394f620de15032090610a4d9084906001909182521515602082015260400190565b6060600e805480602002602001604051908101604052809291908181526020018280548015610bf357602002820191906000526020600020905b815481526020019060010190808311611f7c575050505050905090565b611fa33383612d3d565b611fbf5760405162461bcd60e51b81526004016109f8906158c6565b611fcb8484848461331a565b50505050565b6000828152601560205260408120606091805b825481101561206b57846002811115611fff57611fff615a3b565b61203484838154811061201457612014615a67565b906000526020600020015460009081526001602052604090205460ff1690565b600281111561204557612045615a3b565b14156120595781612055816159e0565b9250505b80612063816159e0565b915050611fe4565b506000816001600160401b0381111561208657612086615a7d565b6040519080825280602002602001820160405280156120af578160200160208202803683370190505b5090506000805b8454811015612157578660028111156120d1576120d1615a3b565b6120e686838154811061201457612014615a67565b60028111156120f7576120f7615a3b565b14156121455784818154811061210f5761210f615a67565b906000526020600020015483838151811061212c5761212c615a67565b602090810291909101015281612141816159e0565b9250505b8061214f816159e0565b9150506120b6565b50909695505050505050565b6060610b658261334d565b6000818152601260209081526040808320548352601090915290205481906001600160a01b0316336001600160a01b0316146121bc5760405162461bcd60e51b81526004016109f89061588f565b60008281526012602052604090819020600301805461ff0019169055517fdacbd8b39f92f5e1f1a3bbbef3779e6a600dc62a4323325cd1676f681197464c90610a4d9084815260200190565b610d9683838360006124e3565b6000612220826134bc565b6000848152601460205260409020805491925090806122725760405162461bcd60e51b815260206004820152600e60248201526d14dd185e481b9bdd08199bdd5b9960921b60448201526064016109f8565b600482015460ff16156122bc5760405162461bcd60e51b815260206004820152601260248201527120b63932b0b23c9031b432b1b5b2b21034b760711b60448201526064016109f8565b60008181526012602090815260408083208054845260109092529091206122e287611b09565b6001600160a01b0316856001600160a01b0316148061230d575080546001600160a01b038681169116145b6123595760405162461bcd60e51b815260206004820152601d60248201527f566f7563686572207369676e6572206973206e6f7420616c6c6f77656400000060448201526064016109f8565b60208601516001600160a01b0316336001600160a01b0316146123ad5760405162461bcd60e51b815260206004820152600c60248201526b2bb937b7339031b0b63632b960a11b60448201526064016109f8565b600282015460048501805460ff191660011790556123e06123cd89611b09565b83546001600160a01b031683878c6135ca565b6040518881527fdf06c27528e294967ba5e32e69b9c5fe102a58c699c44740c2c4c6afc719253590602001611af7565b6012602052600090815260409020805460018201546002830154600384015460048501805494959394929360ff808416946101009094041692909190612455906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054612481906159a5565b80156124ce5780601f106124a3576101008083540402835291602001916124ce565b820191906000526020600020905b8154815290600101906020018083116124b157829003601f168201915b5050505050905086565b610d96838383613650565b61252284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131fa92505050565b600033858560405160200161253993929190615267565b60408051808303601f19018152918152815160209283012060008181526010909352912054909150600160a81b900460ff16156125b85760405162461bcd60e51b815260206004820152601760248201527f466163696c69747920616c72656164792065786973747300000000000000000060448201526064016109f8565b6040518060a001604052806125ca3390565b6001600160a01b03168152602001841515815260200160011515815260200186868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509385525050506001600160a01b03808616602093840152848252601083526040918290208451815486860151948701511515600160a81b0260ff60a81b19951515600160a01b026001600160a81b03199092169290941691909117179290921617815560608301518051919261269992600185019290910190614b92565b5060809190910151600290910180546001600160a01b0319166001600160a01b03909216919091179055600e805460018181019092557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01829055336000818152600f60209081526040808320805495860181558352912090920183905590517f28c9a25063d40c8cf423202182ed575cc97982c1fd1771bd9721e19a38cc491d9061274a90849089908990615764565b60405180910390a25050505050565b601060205260009081526040902080546001820180546001600160a01b0383169360ff600160a01b8504811694600160a81b90041692909161279a906159a5565b80601f01602080910402602001604051908101604052809291908181526020018280546127c6906159a5565b80156128135780601f106127e857610100808354040283529160200191612813565b820191906000526020600020905b8154815290600101906020018083116127f657829003601f168201915b505050600290930154919250506001600160a01b031685565b6060612837826136ef565b6001600160401b0381111561284e5761284e615a7d565b604051908082528060200260200182016040528015612877578160200160208202803683370190505b506000838152601160209081526040808320805482518185028101850190935280835294955092939092918301828280156128d157602002820191906000526020600020905b8154815260200190600101908083116128bd575b50505050509050600080600090505b825181101561297c57601260008483815181106128ff576128ff615a67565b60209081029190910181015182528101919091526040016000206003015460ff161561296a5782818151811061293757612937615a67565b602002602001015184838151811061295157612951615a67565b602090810291909101015281612966816159e0565b9250505b80612974816159e0565b9150506128e0565b505050919050565b6000805b600e548110156129f85760106000600e83815481106129a9576129a9615a67565b9060005260206000200154815260200190815260200160002060000160149054906101000a900460ff16156129e657816129e2816159e0565b9250505b806129f0816159e0565b915050612988565b5090565b60006001600160e01b0319821663780e9d6360e01b1480610b655750610b658261376c565b6000908152600460205260409020546001600160a01b0316151590565b600081815260066020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612a7382611b09565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611fcb848484846137bc565b612ac56202a30042615962565b612ad28362015180615943565b612ae0906362155d6e615917565b11612b265760405162461bcd60e51b8152602060048201526016602482015275111bdb89dd081cdd185e481a5b881d1a19481c185cdd60521b60448201526064016109f8565b60008381526012602090815260408083205483526010909152902054600160a01b900460ff16612b985760405162461bcd60e51b815260206004820152601c60248201527f4c6f6467696e6720466163696c69747920697320696e6163746976650000000060448201526064016109f8565b60008381526012602052604090206003015460ff16612bed5760405162461bcd60e51b8152602060048201526011602482015270537061636520697320696e61637469766560781b60448201526064016109f8565b60008111610d965760405162461bcd60e51b815260206004820152602260248201527f4e756d626572206f6620646179732073686f756c642062652031206f72206d6f604482015261726560f01b60648201526084016109f8565b611ea0828260405180602001604052806000815250613912565b6060612ca5612c738a85858b613945565b612c808a8a8a8a8a613987565b604051602001612c9192919061556f565b6040516020818303038152906040526139e4565b9998505050505050505050565b612cbb82612a21565b612d1e5760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b60648201526084016109f8565b60008281526008602090815260409091208251610d9692840190614b92565b6000612d4882612a21565b612da95760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016109f8565b6000612db483611b09565b9050806001600160a01b0316846001600160a01b03161480612def5750836001600160a01b0316612de484610bfd565b6001600160a01b0316145b8061129d57506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff1661129d565b826001600160a01b0316612e3682611b09565b6001600160a01b031614612e9a5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016109f8565b6001600160a01b038216612efc5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016109f8565b612f07838383613a15565b612f12600082612a3e565b6001600160a01b0383166000908152600560205260408120805460019290612f3b908490615962565b90915550506001600160a01b0382166000908152600560205260408120805460019290612f69908490615917565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60008181526001602052604081205460ff166002811115612fed57612fed615a3b565b146130465760405162461bcd60e51b815260206004820152602360248201527f526566756e64206e6f7420616c6c6f77656420696e2063757272656e7420737460448201526261746560e81b60648201526084016109f8565b6000828152602081815260408083206001600160a01b038716845282528083208484529091529020546130b05760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b60448201526064016109f8565b6000828152602081815260408083206001600160a01b038716808552908352818420858552835281842080549085905560019093529220805460ff19166002179055906130fd9082613a20565b60408051828152602081018590529081018390526001600160a01b038516907fd63bd19af9a43dc55e271643990cc6804dd366f9f50feb7c845c11b9b0664408906060015b60405180910390a250505050565b61315981613b39565b50565b600081815260106020526040902054600160a81b900460ff166131595760405162461bcd60e51b815260206004820152601760248201527f466163696c69747920646f6573206e6f7420657869737400000000000000000060448201526064016109f8565b60008281526010602052604090205481906001600160a01b03163314610d965760405162461bcd60e51b81526004016109f891906157e4565b60008151116131595760405162461bcd60e51b815260206004820152601960248201527f4461746120555249206d7573742062652070726f76696465640000000000000060448201526064016109f8565b816001600160a01b0316836001600160a01b031614156132ad5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016109f8565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613325848484612e23565b61333184848484613b79565b611fcb5760405162461bcd60e51b81526004016109f8906157f7565b606061335882612a21565b6133be5760405162461bcd60e51b815260206004820152603160248201527f45524337323155524953746f726167653a2055524920717565727920666f72206044820152703737b732bc34b9ba32b73a103a37b5b2b760791b60648201526084016109f8565b600082815260086020526040812080546133d7906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054613403906159a5565b80156134505780601f1061342557610100808354040283529160200191613450565b820191906000526020600020905b81548152906001019060200180831161343357829003601f168201915b50505050509050600061346e60408051602081019091526000815290565b9050805160001415613481575092915050565b8151156134b357808260405160200161349b9291906152ad565b60405160208183030381529060405292505050919050565b61129d84613c83565b6000806135407fe14fce867d3bcfe3e7c779de069d9e179b67b9288baf649805c61c495483896b84600001518560200151866040015160405160200161352594939291909384526001600160a01b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613d5b565b9050600080613553838660600151613da9565b9092509050600081600481111561356c5761356c615a3b565b148015613585575084516001600160a01b038381169116145b6135c25760405162461bcd60e51b815260206004820152600e60248201526d213937b5b2b7103b37bab1b432b960911b60448201526064016109f8565b509392505050565b60008281526012602052604090206002015483111561363c5760405162461bcd60e51b815260206004820152602860248201527f576974686472617720616d6f756e74206e6f7420616c6c6f777320696e207468604482015267697320737461746560c01b60648201526084016109f8565b6136498585858585613e19565b5050505050565b6000828152602081815260408083206001600160a01b0387168452825280832084845290915281208054349283929161368a908490615917565b9091555050600082815260016020908152604091829020805460ff1916905581518381529081018590529081018390526001600160a01b038516907f4eef3d1efb11f00508d9b7bb632ddcfa6da9d7105bd39f404bdd7362e6c59dbc90606001613142565b6000818152601160205260408120815b8154811015613765576012600083838154811061371e5761371e615a67565b6000918252602080832090910154835282019290925260400190206003015460ff1615613753578261374f816159e0565b9350505b8061375d816159e0565b9150506136ff565b5050919050565b60006001600160e01b031982166380ac58cd60e01b148061379d57506001600160e01b03198216635b5e139f60e01b145b80610b6557506301ffc9a760e01b6001600160e01b0319831614610b65565b6000828152602081815260408083206001600160a01b0388168452825280832084845282528083205460019283905292205460ff16600281111561380257613802615a3b565b146138635760405162461bcd60e51b815260206004820152602b60248201527f436f6d706c657465207769746864726177206e6f7420616c6c6f77656420696e60448201526a207468697320737461746560a81b60648201526084016109f8565b6000838152602081815260408083206001600160a01b03891684528252808320858452825280832083905560019091529020805460ff191660021790558015613649576138b96001600160a01b03851682613a20565b60408051828152602081018590529081018390526001600160a01b0380861691908716907f89eeb38ad2da123e4b3662ad415c1856733f76deaccee072a5234ab427ffdb70906060015b60405180910390a35050505050565b61391c8383613f5d565b6139296000848484613b79565b610d965760405162461bcd60e51b81526004016109f8906157f7565b60606139508561409c565b848461395b85614199565b60405160200161396e9493929190615470565b6040516020818303038152906040529050949350505050565b606061399286614199565b61399b86614199565b6139a48661409c565b6139ad8661409c565b6139b68661409c565b6040516020016139ca9594939291906152dc565b604051602081830303815290604052905095945050505050565b60606139ef826141d4565b6040516020016139ff91906155c6565b6040516020818303038152906040529050919050565b610d96838383614327565b80471015613a705760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016109f8565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613abd576040519150601f19603f3d011682016040523d82523d6000602084013e613ac2565b606091505b5050905080610d965760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016109f8565b613b42816143df565b60008181526008602052604090208054613b5b906159a5565b15905061315957600081815260086020526040812061315991614c06565b60006001600160a01b0384163b15613c7b57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290613bbd90339089908890889060040161560b565b602060405180830381600087803b158015613bd757600080fd5b505af1925050508015613c07575060408051601f3d908101601f19168201909252613c0491810190615068565b60015b613c61573d808015613c35576040519150601f19603f3d011682016040523d82523d6000602084013e613c3a565b606091505b508051613c595760405162461bcd60e51b81526004016109f8906157f7565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061129d565b50600161129d565b6060613c8e82612a21565b613cf25760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016109f8565b6000613d0960408051602081019091526000815290565b90506000815111613d295760405180602001604052806000815250613d54565b80613d3384614486565b604051602001613d449291906152ad565b6040516020818303038152906040525b9392505050565b6000610b65613d68614583565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080825160411415613de05760208301516040840151606085015160001a613dd4878285856146aa565b94509450505050613e12565b825160401415613e0a5760208301516040840151613dff868383614797565b935093505050613e12565b506000905060025b9250929050565b6000828152602081815260408083206001600160a01b03891684528252808320848452909152902054831115613e865760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b60448201526064016109f8565b6000828152602081815260408083206001600160a01b03891684528252808320848452909152902054613eba908490615962565b6000838152602081815260408083206001600160a01b038a1684528252808320858452825280832093909355600190819052919020805460ff191682800217905550613f0f6001600160a01b03851684613a20565b60408051848152602081018490529081018290526001600160a01b0380861691908716907f89eeb38ad2da123e4b3662ad415c1856733f76deaccee072a5234ab427ffdb7090606001613903565b6001600160a01b038216613fb35760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016109f8565b613fbc81612a21565b156140095760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016109f8565b61401560008383613a15565b6001600160a01b038216600090815260056020526040812080546001929061403e908490615917565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060816140c05750506040805180820190915260018152600360fc1b602082015290565b8160005b81156140ea57806140d4816159e0565b91506140e39050600a8361592f565b91506140c4565b6000816001600160401b0381111561410457614104615a7d565b6040519080825280601f01601f19166020018201604052801561412e576020820181803683370190505b5090505b841561129d57614143600183615962565b9150614150600a866159fb565b61415b906030615917565b60f81b81838151811061417057614170615a67565b60200101906001600160f81b031916908160001a905350614192600a8661592f565b9450614132565b60606141a4826147d0565b6141b1608084901b6147d0565b60405161060f60f31b6020820152602281019290925260428201526062016139ff565b60608151600014156141f457505060408051602081019091526000815290565b6000604051806060016040528060408152602001615acc60409139905060006003845160026142239190615917565b61422d919061592f565b614238906004615943565b6001600160401b0381111561424f5761424f615a7d565b6040519080825280601f01601f191660200182016040528015614279576020820181803683370190505b509050600182016020820185865187015b808210156142e5576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f811685015184535060018301925061428a565b505060038651066001811461430157600281146143145761431c565b603d6001830353603d600283035361431c565b603d60018303535b509195945050505050565b6001600160a01b0383166143825761437d81600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6143a5565b816001600160a01b0316836001600160a01b0316146143a5576143a58382614982565b6001600160a01b0382166143bc57610d9681614a1f565b826001600160a01b0316826001600160a01b031614610d9657610d968282614ace565b60006143ea82611b09565b90506143f881600084613a15565b614403600083612a3e565b6001600160a01b038116600090815260056020526040812080546001929061442c908490615962565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6060816144aa5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156144d457806144be816159e0565b91506144cd9050600a8361592f565b91506144ae565b6000816001600160401b038111156144ee576144ee615a7d565b6040519080825280601f01601f191660200182016040528015614518576020820181803683370190505b5090505b841561129d5761452d600183615962565b915061453a600a866159fb565b614545906030615917565b60f81b81838151811061455a5761455a615a67565b60200101906001600160f81b031916908160001a90535061457c600a8661592f565b945061451c565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156145dc57507f000000000000000000000000000000000000000000000000000000000000000046145b1561460657507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156146e1575060009050600361478e565b8460ff16601b141580156146f957508460ff16601c14155b1561470a575060009050600461478e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561475e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166147875760006001925092505061478e565b9150600090505b94509492505050565b6000806001600160ff1b038316816147b460ff86901c601b615917565b90506147c2878288856146aa565b935093505050935093915050565b7aff00000000000000ff00000000000000ff00000000000000ff00006bffffffff0000000000000000604083901c90811663ffffffff60c01b84161760201c63ffffffff60601b919091166001600160e01b031984161717601081901c9182167eff00000000000000ff00000000000000ff00000000000000ff000000000000821617600890811c7bff00000000000000ff00000000000000ff00000000000000ff000000939093167fff00000000000000ff00000000000000ff00000000000000ff000000000000009290921691909117919091179081901c7e0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f167f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00600492831c16179061491e827f0606060606060606060606060606060606060606060606060606060606060606615917565b901c7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16600761494e9190615943565b614978827f3030303030303030303030303030303030303030303030303030303030303030615917565b610b659190615917565b6000600161498f84611c43565b6149999190615962565b6000838152600a60205260409020549091508082146149ec576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090614a3190600190615962565b6000838152600c6020526040812054600b8054939450909284908110614a5957614a59615a67565b9060005260206000200154905080600b8381548110614a7a57614a7a615a67565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480614ab257614ab2615a51565b6001900381819060005260206000200160009055905550505050565b6000614ad983611c43565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b828054614b1e906159a5565b90600052602060002090601f016020900481019282614b405760008555614b86565b82601f10614b595782800160ff19823516178555614b86565b82800160010185558215614b86579182015b82811115614b86578235825591602001919060010190614b6b565b506129f8929150614c3c565b828054614b9e906159a5565b90600052602060002090601f016020900481019282614bc05760008555614b86565b82601f10614bd957805160ff1916838001178555614b86565b82800160010185558215614b86579182015b82811115614b86578251825591602001919060010190614beb565b508054614c12906159a5565b6000825580601f10614c22575050565b601f01602090049060005260206000209081019061315991905b5b808211156129f85760008155600101614c3d565b80356001600160a01b0381168114614c6857600080fd5b919050565b80358015158114614c6857600080fd5b600082601f830112614c8e57600080fd5b81356001600160401b0380821115614ca857614ca8615a7d565b604051601f8301601f19908116603f01168101908282118183101715614cd057614cd0615a7d565b81604052838152866020858801011115614ce957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008083601f840112614d1b57600080fd5b5081356001600160401b03811115614d3257600080fd5b602083019150836020828501011115613e1257600080fd5b600060208284031215614d5c57600080fd5b613d5482614c51565b60008060408385031215614d7857600080fd5b614d8183614c51565b9150614d8f60208401614c51565b90509250929050565b600080600060608486031215614dad57600080fd5b614db684614c51565b9250614dc460208501614c51565b9150604084013590509250925092565b60008060008060808587031215614dea57600080fd5b614df385614c51565b9350614e0160208601614c51565b92506040850135915060608501356001600160401b03811115614e2357600080fd5b614e2f87828801614c7d565b91505092959194509250565b60008060408385031215614e4e57600080fd5b614e5783614c51565b9150614d8f60208401614c6d565b600080600060608486031215614e7a57600080fd5b614e8384614c51565b95602085013595506040909401359392505050565b60008060408385031215614eab57600080fd5b614eb483614c51565b946020939093013593505050565b600060208284031215614ed457600080fd5b5035919050565b60008060408385031215614eee57600080fd5b82359150614d8f60208401614c51565b60008060408385031215614f1157600080fd5b82359150602083013560038110614f2757600080fd5b809150509250929050565b600080600060408486031215614f4757600080fd5b8335925060208401356001600160401b03811115614f6457600080fd5b614f7086828701614d09565b9497909650939450505050565b600080600060608486031215614f9257600080fd5b505081359360208301359350604090920135919050565b60008060008060008060a08789031215614fc257600080fd5b863595506020870135945060408701359350614fe060608801614c6d565b925060808701356001600160401b03811115614ffb57600080fd5b61500789828a01614d09565b979a9699509497509295939492505050565b6000806000806080858703121561502f57600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561505d57600080fd5b8135613d5481615a93565b60006020828403121561507a57600080fd5b8151613d5481615a93565b60008060006040848603121561509a57600080fd5b83356001600160401b038111156150b057600080fd5b6150bc86828701614d09565b90945092506150cf905060208501614c6d565b90509250925092565b600080600080606085870312156150ee57600080fd5b84356001600160401b0381111561510457600080fd5b61511087828801614d09565b9095509350615123905060208601614c6d565b915061513160408601614c51565b905092959194509250565b6000806040838503121561514f57600080fd5b8235915060208301356001600160401b038082111561516d57600080fd5b908401906080828703121561518157600080fd5b60405160808101818110838211171561519c5761519c615a7d565b6040526151a883614c51565b81526151b660208401614c51565b6020820152604083013560408201526060830135828111156151d757600080fd5b6151e388828601614c7d565b6060830152508093505050509250929050565b6000815180845261520e816020860160208601615979565b601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000815161525d818560208601615979565b9290920192915050565b6bffffffffffffffffffffffff198460601b168152818360148301376000910160140190815292915050565b838152818360208301376000910160200190815292915050565b600083516152bf818460208801615979565b8351908301906152d3818360208801615979565b01949350505050565b7f2261747472696275746573223a5b7b2274726169745f74797065223a2266616381527134b634ba3ca4b21116113b30b63ab2911d1160711b60208201526000865161532f816032850160208b01615979565b7f227d2c7b2274726169745f74797065223a2273706163654964222c2276616c756032918401918201526332911d1160e11b60528201528651615379816056840160208b01615979565b7f227d2c7b2274726169745f74797065223a227374617274446179222c2276616c60569290910191820152643ab2911d1160d91b607682015285516153c581607b840160208a01615979565b7f227d2c7b2274726169745f74797065223a226e756d6265724f6644617973222c607b929091019182015268113b30b63ab2911d1160b91b609b82015261546461545561544f61541860a485018961524b565b7f227d2c7b2274726169745f74797065223a227175616e74697479222c2276616c8152643ab2911d1160d91b602082015260250190565b8661524b565b62227d5d60e81b815260030190565b98975050505050505050565b72226e616d65223a2253746179546f6b656e202360681b8152845160009061549f816013850160208a01615979565b7f222c226465736372697074696f6e223a2253746179206174206c6f6467696e6760139184019182015273103330b1b4b634ba3c91161134b6b0b3b2911d1160611b603382015285516154f9816047840160208a01615979565b7111161132bc3a32b93730b62fbab936111d1160711b60479290910191820152845161552c816059840160208901615979565b6573706163652f60d01b60599290910191820152835161555381605f840160208801615979565b601160f91b605f92909101918201526060019695505050505050565b607b60f81b81526000835161558b816001850160208801615979565b600b60fa1b60019184019182015283516155ac816002840160208801615979565b607d60f81b60029290910191820152600301949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516155fe81601d850160208701615979565b91909101601d0192915050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061563e908301846151f6565b9695505050505050565b600060018060a01b0380881683528615156020840152851515604084015260a0606084015261567a60a08401866151f6565b91508084166080840152509695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612157578351835292840192918401916001016156ab565b84151581526001600160a01b0384166020820152821515604082015260806060820181905260009061563e908301846151f6565b8615158152856020820152846040820152836060820152821515608082015260c060a0820152600061546460c08301846151f6565b878152866020820152856040820152846060820152831515608082015260c060a08201526000612ca560c083018486615222565b83815260406020820152600061577e604083018486615222565b95945050505050565b8681528560208201528460408201528315156060820152821515608082015260c060a0820152600061546460c08301846151f6565b60208101600383106157de57634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000613d5460208301846151f6565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f6e6c79206c6f6467696e6720666163696c697479206f776e657220697320616040820152651b1b1bddd95960d21b606082015260800190565b6020808252601b908201527f4f6e6c79207370616365206f776e657220697320616c6c6f7765640000000000604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000821982111561592a5761592a615a0f565b500190565b60008261593e5761593e615a25565b500490565b600081600019048311821515161561595d5761595d615a0f565b500290565b60008282101561597457615974615a0f565b500390565b60005b8381101561599457818101518382015260200161597c565b83811115611fcb5750506000910152565b600181811c908216806159b957607f821691505b602082108114156159da57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156159f4576159f4615a0f565b5060010190565b600082615a0a57615a0a615a25565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461315957600080fdfe4f6e6c7920666163696c697479206f776e6572206d617920616464205370616365734142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f68747470733a2f2f626166796265696767376d7777706e6e6d366d6d6b3374777863346172697a6f796336696a6e617965337064636977636f6868656f37786937686d2e697066732e647765622e6c696e6b2f746f6b656e2d696d6167652e706e67a2646970667358221220701949743df2e1d7092f946646e5c1cecd46d4e618b8c5d58c02647da652bbe564736f6c63430008070033
Deployed ByteCode
0x6080604052600436106102c75760003560e01c80636a22dd2611610175578063c87b56dd116100dc578063e6ccb4ce11610095578063eb2243f81161006f578063eb2243f814610933578063f7cdbc9d14610946578063ffae741514610966578063ffc1e09a1461099757600080fd5b8063e6ccb4ce14610898578063e985e9c5146108b8578063e994529e1461090157600080fd5b8063c87b56dd146107f5578063cad302e414610815578063cf63247e146105ab578063d0470d7c14610858578063e1e33b9c14610878578063e3aae3a5146105ab57600080fd5b80639ff682141161012e5780639ff6821414610733578063a22cb46514610760578063a468803214610780578063b38759fd146107a0578063b88d4fde146107b5578063bfef4d40146107d557600080fd5b80636a22dd261461067e57806370a082311461069e57806380d288f2146106be5780638f201f5f146106de5780639518f5fa146106fe57806395d89b411461071e57600080fd5b806323b872dd11610234578063438c9cab116101ed5780634f6ccce7116101c75780634f6ccce7146105fe5780635ee7aa131461061e5780636352211e1461063e578063673f0dd51461065e57600080fd5b8063438c9cab1461058b578063462ef5ed146105ab5780634c18a8ec146105ce57600080fd5b806323b872dd146104b957806327d7cedb146104d95780632f745c59146104f9578063342df9b21461051957806340e58ee51461054b57806342842e0e1461056b57600080fd5b8063095ea7b311610286578063095ea7b3146103e057806318160ddd146104005780631b9bdb121461041f5780631bd2eeee146104665780631bf7509b1461048657806320bf6ddb146104a657600080fd5b8062442536146102cc578062d34b54146102ee57806301ffc9a714610319578063038c89751461034957806306fdde0314610386578063081812fc146103a8575b600080fd5b3480156102d857600080fd5b506102ec6102e7366004614ec2565b6109b7565b005b3480156102fa57600080fd5b50610303610a59565b604051610310919061568f565b60405180910390f35b34801561032557600080fd5b5061033961033436600461504b565b610b5a565b6040519015158152602001610310565b34801561035557600080fd5b50610379610364366004614ec2565b60009081526001602052604090205460ff1690565b60405161031091906157bc565b34801561039257600080fd5b5061039b610b6b565b60405161031091906157e4565b3480156103b457600080fd5b506103c86103c3366004614ec2565b610bfd565b6040516001600160a01b039091168152602001610310565b3480156103ec57600080fd5b506102ec6103fb366004614e98565b610c85565b34801561040c57600080fd5b50600b545b604051908152602001610310565b34801561042b57600080fd5b5061041161043a366004614e65565b6000918252602082815260408084206001600160a01b0395909516845293815283832091835252205490565b34801561047257600080fd5b506102ec610481366004614ec2565b610d9b565b34801561049257600080fd5b506103036104a1366004614d4a565b610f5b565b6104116104b4366004615019565b610fc7565b3480156104c557600080fd5b506102ec6104d4366004614d98565b6112a5565b3480156104e557600080fd5b506103036104f4366004614f7d565b6112d6565b34801561050557600080fd5b50610411610514366004614e98565b611491565b34801561052557600080fd5b50610539610534366004614ec2565b611527565b604051610310969594939291906156fb565b34801561055757600080fd5b506102ec610566366004614ec2565b6115f6565b34801561057757600080fd5b506102ec610586366004614d98565b6116ba565b34801561059757600080fd5b506102ec6105a6366004614f32565b6116d5565b3480156105b757600080fd5b5061039b6040518060200160405280600081525081565b3480156105da57600080fd5b506105ee6105e9366004614ec2565b611766565b60405161031094939291906156c7565b34801561060a57600080fd5b50610411610619366004614ec2565b611832565b34801561062a57600080fd5b506102ec610639366004614fa9565b6118c5565b34801561064a57600080fd5b506103c8610659366004614ec2565b611b09565b34801561066a57600080fd5b50610539610679366004614ec2565b611b80565b34801561068a57600080fd5b506102ec610699366004614ec2565b611bb7565b3480156106aa57600080fd5b506104116106b9366004614d4a565b611c43565b3480156106ca57600080fd5b506102ec6106d9366004614fa9565b611cca565b3480156106ea57600080fd5b506102ec6106f9366004614edb565b611d65565b34801561070a57600080fd5b50610303610719366004614ec2565b611e26565b34801561072a57600080fd5b5061039b611e86565b34801561073f57600080fd5b5061074b6362155d6e81565b60405163ffffffff9091168152602001610310565b34801561076c57600080fd5b506102ec61077b366004614e3b565b611e95565b34801561078c57600080fd5b506102ec61079b366004614ec2565b611ea4565b3480156107ac57600080fd5b50610303611f42565b3480156107c157600080fd5b506102ec6107d0366004614dd4565b611f99565b3480156107e157600080fd5b506103036107f0366004614efe565b611fd1565b34801561080157600080fd5b5061039b610810366004614ec2565b612163565b34801561082157600080fd5b5061039b6040518060400160405280601781526020017668747470733a2f2f6c6f63616c686f73743a333030302f60481b81525081565b34801561086457600080fd5b506102ec610873366004614ec2565b61216e565b34801561088457600080fd5b506102ec610893366004615085565b612208565b3480156108a457600080fd5b506102ec6108b336600461513c565b612215565b3480156108c457600080fd5b506103396108d3366004614d65565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b34801561090d57600080fd5b5061092161091c366004614ec2565b612410565b60405161031096959493929190615787565b6102ec610941366004614e65565b6124d8565b34801561095257600080fd5b506102ec6109613660046150d8565b6124e3565b34801561097257600080fd5b50610986610981366004614ec2565b612759565b604051610310959493929190615648565b3480156109a357600080fd5b506103036109b2366004614ec2565b61282c565b60008181526010602052604090205481906001600160a01b0316336001600160a01b031614610a015760405162461bcd60e51b81526004016109f890615849565b60405180910390fd5b6000828152601060209081526040808320805460ff60a01b191690558051858152918201929092527f5c33859dfe8722791b5d72ad942a0895181f8a694288ec429394f620de15032091015b60405180910390a15050565b6060610a63612984565b6001600160401b03811115610a7a57610a7a615a7d565b604051908082528060200260200182016040528015610aa3578160200160208202803683370190505b5090506000805b600e54811015610b555760106000600e8381548110610acb57610acb615a67565b9060005260206000200154815260200190815260200160002060000160149054906101000a900460ff1615610b4357600e8181548110610b0d57610b0d615a67565b9060005260206000200154838381518110610b2a57610b2a615a67565b602090810291909101015281610b3f816159e0565b9250505b80610b4d816159e0565b915050610aaa565b505090565b6000610b65826129fc565b92915050565b606060028054610b7a906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054610ba6906159a5565b8015610bf35780601f10610bc857610100808354040283529160200191610bf3565b820191906000526020600020905b815481529060010190602001808311610bd657829003601f168201915b5050505050905090565b6000610c0882612a21565b610c695760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016109f8565b506000908152600660205260409020546001600160a01b031690565b6000610c9082611b09565b9050806001600160a01b0316836001600160a01b03161415610cfe5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084016109f8565b336001600160a01b0382161480610d1a5750610d1a81336108d3565b610d8c5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016109f8565b610d968383612a3e565b505050565b60008181526014602052604090208054610de85760405162461bcd60e51b815260206004820152600e60248201526d14dd185e481b9bdd08199bdd5b9960921b60448201526064016109f8565b6004810154610100900460ff1615610e385760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e4818da1958dad959081bdd5d606a1b60448201526064016109f8565b8054600081815260126020908152604080832054835260109091529020546001600160a01b0316338114610e7e5760405162461bcd60e51b81526004016109f89061588f565b82600201548360010154610e929190615917565b610e9f9062015180615943565b610ead906362155d6e615917565b421015610efc5760405162461bcd60e51b815260206004820152601e60248201527f466f7262696464656e20756e6c65737320636865636b6f75742064617465000060448201526064016109f8565b60048301805461ff001916610100179055610f21610f1985611b09565b828487612aac565b6040518481527f2c276699fefbad45f18509233bc03bb9cfdf41b18f32756933188bdef35fef55906020015b60405180910390a150505050565b6001600160a01b0381166000908152600f6020908152604091829020805483518184028101840190945280845260609392830182828015610fbb57602002820191906000526020600020905b815481526020019060010190808311610fa7575b50505050509050919050565b6000610fd4858585612ab8565b60008581526012602052604081206002810154909190610ff48587615943565b610ffe9190615943565b9050803410156110455760405162461bcd60e51b81526020600482015260126024820152714e6565642e204d6f72652e204d6f6e65792160701b60448201526064016109f8565b60005b8581101561111e576000888152601360205260408120869161106a848b615917565b81526020019081526020016000205484600101546110889190615962565b10156110cf5760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420696e76656e746f727960501b60448201526064016109f8565b600088815260136020526040812086916110e9848b615917565b815260200190815260200160002060008282546111069190615917565b90915550819050611116816159e0565b915050611048565b5061112d600d80546001019055565b6000611138600d5490565b90506111443382612c48565b60006111a18285600001548b8b8b8b6040518060a0016040528060628152602001615b0c606291396040518060400160405280601781526020017668747470733a2f2f6c6f63616c686f73743a333030302f60481b815250612c62565b90506111ad8282612cb2565b6040805160c0810182528a815260208082018b81528284018b8152606084018b815260006080860181815260a087018281528a8352601487528883209751885594516001888101919091559351600288015591516003870155905160049095018054935115156101000261ff00199615159690961661ffff1990941693909317949094179091558c83526015825292822080549384018155825290200182905561125e6112573390565b8a846124d8565b604080518a8152602081018490527fe04083eb622e3cb7d063f319076c83270c24acb409a3bc13abcfb36af60f8617910160405180910390a150925050505b949350505050565b6112af3382612d3d565b6112cb5760405162461bcd60e51b81526004016109f8906158c6565b610d96838383612e23565b60606112e3848484612ab8565b6000848152601260209081526040808320815160c08101835281548152600182015493810193909352600281015491830191909152600381015460ff80821615156060850152610100909104161515608083015260048101805460a08401919061134c906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054611378906159a5565b80156113c55780601f1061139a576101008083540402835291602001916113c5565b820191906000526020600020905b8154815290600101906020018083116113a857829003601f168201915b50505050508152505090506000836001600160401b038111156113ea576113ea615a7d565b604051908082528060200260200182016040528015611413578160200160208202803683370190505b50905060005b848110156114875760008781526013602052604081209061143a8389615917565b81526020019081526020016000205483602001516114589190615962565b82828151811061146a5761146a615a67565b60209081029190910101528061147f816159e0565b915050611419565b5095945050505050565b600061149c83611c43565b82106114fe5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016109f8565b506001600160a01b03919091166000908152600960209081526040808320938352929052205490565b6000818152601260205260409020600381015481546001830154600284015460048501805460ff61010087048116979596949593941692606092909161156c906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054611598906159a5565b80156115e55780601f106115ba576101008083540402835291602001916115e5565b820191906000526020600020905b8154815290600101906020018083116115c857829003601f168201915b505050505091505091939550919395565b8061160081611b09565b6001600160a01b0316336001600160a01b0316146116605760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79207374617920746f6b656e206f776e657220697320616c6c6f77656460448201526064016109f8565b61168161166c83611b09565b60008481526014602052604090205484612fca565b61168a82613150565b6040518281527f8bf30e7ff26833413be5f69e1d373744864d600b664204b4a2f9844a8eedb9ed90602001610a4d565b610d9683838360405180602001604052806000815250611f99565b60008381526010602052604090205483906001600160a01b0316336001600160a01b0316146117165760405162461bcd60e51b81526004016109f890615849565b6000848152601060205260409020611732906001018484614b12565b507fb252d91e8d424ba6f9f1647d21d7b0bbd8e2a3cbb318aaecb0d735fba9f62c7f848484604051610f4d93929190615764565b6000818152601060205260409020805460018201805460ff600160a81b84048116946001600160a01b03851694600160a01b9004909116926060926117aa906159a5565b80601f01602080910402602001604051908101604052809291908181526020018280546117d6906159a5565b80156118235780601f106117f857610100808354040283529160200191611823565b820191906000526020600020905b81548152906001019060200180831161180657829003601f168201915b50505050509150509193509193565b600061183d600b5490565b82106118a05760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016109f8565b600b82815481106118b3576118b3615a67565b90600052602060002001549050919050565b856118cf8161315c565b6118f181604051806060016040528060228152602001615aaa602291396131c1565b61193083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131fa92505050565b600081848460405160200161194793929190615293565b60408051808303601f19018152918152815160209283012060008181526012909352912060030154909150610100900460ff16156119be5760405162461bcd60e51b8152602060048201526014602482015273537061636520616c72656164792065786973747360601b60448201526064016109f8565b6040518060c00160405280838152602001888152602001878152602001861515815260200160011515815260200185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093909452505083815260126020908152604091829020845181558482015160018201559184015160028301556060840151600383018054608087015115156101000261ff00199315159390931661ffff199091161791909117905560a08401518051929350611a969260048501929190910190614b92565b505050600082815260116020908152604080832080546001810182559084529190922001829055517f335958c15e70938d2bfae6c90457d7732a3e398f2423c491dc6503b67334745a90611af790839085908b908b908b908b908b90615730565b60405180910390a15050505050505050565b6000818152600460205260408120546001600160a01b031680610b655760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b60648201526084016109f8565b6000818152601460205260408120548190819081908190606090611ba390611527565b949c939b5091995097509550909350915050565b60008181526010602052604090205481906001600160a01b0316336001600160a01b031614611bf85760405162461bcd60e51b81526004016109f890615849565b60008281526010602052604090819020805460ff60a81b19169055517f9cb52f05776b0f321eb9ca8c9e1b26b978036072417bf384bd406189f43864f890610a4d9084815260200190565b60006001600160a01b038216611cae5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b60648201526084016109f8565b506001600160a01b031660009081526005602052604090205490565b6000868152601260209081526040808320548352601090915290205486906001600160a01b0316336001600160a01b031614611d185760405162461bcd60e51b81526004016109f89061588f565b600087815260126020526040908190208054915190917f335958c15e70938d2bfae6c90457d7732a3e398f2423c491dc6503b67334745a91611af7918b918b908b908b908b908b90615730565b60008281526010602052604090205482906001600160a01b0316336001600160a01b031614611da65760405162461bcd60e51b81526004016109f890615849565b6000838152601060209081526040918290205491518581526001600160a01b038581169316917f11a520c5c4bfade8b450399ea67096dba36478d23d9a45f02e32989cfe307dde910160405180910390a35060009182526010602052604090912080546001600160a01b0319166001600160a01b03909216919091179055565b600081815260116020908152604091829020805483518184028101840190945280845260609392830182828015610fbb5760200282019190600052602060002090815481526020019060010190808311610fa75750505050509050919050565b606060038054610b7a906159a5565b611ea033838361324b565b5050565b60008181526010602052604090205481906001600160a01b0316336001600160a01b031614611ee55760405162461bcd60e51b81526004016109f890615849565b60008281526010602052604090819020805460ff60a01b1916600160a01b179055517f5c33859dfe8722791b5d72ad942a0895181f8a694288ec429394f620de15032090610a4d9084906001909182521515602082015260400190565b6060600e805480602002602001604051908101604052809291908181526020018280548015610bf357602002820191906000526020600020905b815481526020019060010190808311611f7c575050505050905090565b611fa33383612d3d565b611fbf5760405162461bcd60e51b81526004016109f8906158c6565b611fcb8484848461331a565b50505050565b6000828152601560205260408120606091805b825481101561206b57846002811115611fff57611fff615a3b565b61203484838154811061201457612014615a67565b906000526020600020015460009081526001602052604090205460ff1690565b600281111561204557612045615a3b565b14156120595781612055816159e0565b9250505b80612063816159e0565b915050611fe4565b506000816001600160401b0381111561208657612086615a7d565b6040519080825280602002602001820160405280156120af578160200160208202803683370190505b5090506000805b8454811015612157578660028111156120d1576120d1615a3b565b6120e686838154811061201457612014615a67565b60028111156120f7576120f7615a3b565b14156121455784818154811061210f5761210f615a67565b906000526020600020015483838151811061212c5761212c615a67565b602090810291909101015281612141816159e0565b9250505b8061214f816159e0565b9150506120b6565b50909695505050505050565b6060610b658261334d565b6000818152601260209081526040808320548352601090915290205481906001600160a01b0316336001600160a01b0316146121bc5760405162461bcd60e51b81526004016109f89061588f565b60008281526012602052604090819020600301805461ff0019169055517fdacbd8b39f92f5e1f1a3bbbef3779e6a600dc62a4323325cd1676f681197464c90610a4d9084815260200190565b610d9683838360006124e3565b6000612220826134bc565b6000848152601460205260409020805491925090806122725760405162461bcd60e51b815260206004820152600e60248201526d14dd185e481b9bdd08199bdd5b9960921b60448201526064016109f8565b600482015460ff16156122bc5760405162461bcd60e51b815260206004820152601260248201527120b63932b0b23c9031b432b1b5b2b21034b760711b60448201526064016109f8565b60008181526012602090815260408083208054845260109092529091206122e287611b09565b6001600160a01b0316856001600160a01b0316148061230d575080546001600160a01b038681169116145b6123595760405162461bcd60e51b815260206004820152601d60248201527f566f7563686572207369676e6572206973206e6f7420616c6c6f77656400000060448201526064016109f8565b60208601516001600160a01b0316336001600160a01b0316146123ad5760405162461bcd60e51b815260206004820152600c60248201526b2bb937b7339031b0b63632b960a11b60448201526064016109f8565b600282015460048501805460ff191660011790556123e06123cd89611b09565b83546001600160a01b031683878c6135ca565b6040518881527fdf06c27528e294967ba5e32e69b9c5fe102a58c699c44740c2c4c6afc719253590602001611af7565b6012602052600090815260409020805460018201546002830154600384015460048501805494959394929360ff808416946101009094041692909190612455906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054612481906159a5565b80156124ce5780601f106124a3576101008083540402835291602001916124ce565b820191906000526020600020905b8154815290600101906020018083116124b157829003601f168201915b5050505050905086565b610d96838383613650565b61252284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131fa92505050565b600033858560405160200161253993929190615267565b60408051808303601f19018152918152815160209283012060008181526010909352912054909150600160a81b900460ff16156125b85760405162461bcd60e51b815260206004820152601760248201527f466163696c69747920616c72656164792065786973747300000000000000000060448201526064016109f8565b6040518060a001604052806125ca3390565b6001600160a01b03168152602001841515815260200160011515815260200186868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509385525050506001600160a01b03808616602093840152848252601083526040918290208451815486860151948701511515600160a81b0260ff60a81b19951515600160a01b026001600160a81b03199092169290941691909117179290921617815560608301518051919261269992600185019290910190614b92565b5060809190910151600290910180546001600160a01b0319166001600160a01b03909216919091179055600e805460018181019092557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01829055336000818152600f60209081526040808320805495860181558352912090920183905590517f28c9a25063d40c8cf423202182ed575cc97982c1fd1771bd9721e19a38cc491d9061274a90849089908990615764565b60405180910390a25050505050565b601060205260009081526040902080546001820180546001600160a01b0383169360ff600160a01b8504811694600160a81b90041692909161279a906159a5565b80601f01602080910402602001604051908101604052809291908181526020018280546127c6906159a5565b80156128135780601f106127e857610100808354040283529160200191612813565b820191906000526020600020905b8154815290600101906020018083116127f657829003601f168201915b505050600290930154919250506001600160a01b031685565b6060612837826136ef565b6001600160401b0381111561284e5761284e615a7d565b604051908082528060200260200182016040528015612877578160200160208202803683370190505b506000838152601160209081526040808320805482518185028101850190935280835294955092939092918301828280156128d157602002820191906000526020600020905b8154815260200190600101908083116128bd575b50505050509050600080600090505b825181101561297c57601260008483815181106128ff576128ff615a67565b60209081029190910181015182528101919091526040016000206003015460ff161561296a5782818151811061293757612937615a67565b602002602001015184838151811061295157612951615a67565b602090810291909101015281612966816159e0565b9250505b80612974816159e0565b9150506128e0565b505050919050565b6000805b600e548110156129f85760106000600e83815481106129a9576129a9615a67565b9060005260206000200154815260200190815260200160002060000160149054906101000a900460ff16156129e657816129e2816159e0565b9250505b806129f0816159e0565b915050612988565b5090565b60006001600160e01b0319821663780e9d6360e01b1480610b655750610b658261376c565b6000908152600460205260409020546001600160a01b0316151590565b600081815260066020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612a7382611b09565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b611fcb848484846137bc565b612ac56202a30042615962565b612ad28362015180615943565b612ae0906362155d6e615917565b11612b265760405162461bcd60e51b8152602060048201526016602482015275111bdb89dd081cdd185e481a5b881d1a19481c185cdd60521b60448201526064016109f8565b60008381526012602090815260408083205483526010909152902054600160a01b900460ff16612b985760405162461bcd60e51b815260206004820152601c60248201527f4c6f6467696e6720466163696c69747920697320696e6163746976650000000060448201526064016109f8565b60008381526012602052604090206003015460ff16612bed5760405162461bcd60e51b8152602060048201526011602482015270537061636520697320696e61637469766560781b60448201526064016109f8565b60008111610d965760405162461bcd60e51b815260206004820152602260248201527f4e756d626572206f6620646179732073686f756c642062652031206f72206d6f604482015261726560f01b60648201526084016109f8565b611ea0828260405180602001604052806000815250613912565b6060612ca5612c738a85858b613945565b612c808a8a8a8a8a613987565b604051602001612c9192919061556f565b6040516020818303038152906040526139e4565b9998505050505050505050565b612cbb82612a21565b612d1e5760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b60648201526084016109f8565b60008281526008602090815260409091208251610d9692840190614b92565b6000612d4882612a21565b612da95760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084016109f8565b6000612db483611b09565b9050806001600160a01b0316846001600160a01b03161480612def5750836001600160a01b0316612de484610bfd565b6001600160a01b0316145b8061129d57506001600160a01b0380821660009081526007602090815260408083209388168352929052205460ff1661129d565b826001600160a01b0316612e3682611b09565b6001600160a01b031614612e9a5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016109f8565b6001600160a01b038216612efc5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016109f8565b612f07838383613a15565b612f12600082612a3e565b6001600160a01b0383166000908152600560205260408120805460019290612f3b908490615962565b90915550506001600160a01b0382166000908152600560205260408120805460019290612f69908490615917565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60008181526001602052604081205460ff166002811115612fed57612fed615a3b565b146130465760405162461bcd60e51b815260206004820152602360248201527f526566756e64206e6f7420616c6c6f77656420696e2063757272656e7420737460448201526261746560e81b60648201526084016109f8565b6000828152602081815260408083206001600160a01b038716845282528083208484529091529020546130b05760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b60448201526064016109f8565b6000828152602081815260408083206001600160a01b038716808552908352818420858552835281842080549085905560019093529220805460ff19166002179055906130fd9082613a20565b60408051828152602081018590529081018390526001600160a01b038516907fd63bd19af9a43dc55e271643990cc6804dd366f9f50feb7c845c11b9b0664408906060015b60405180910390a250505050565b61315981613b39565b50565b600081815260106020526040902054600160a81b900460ff166131595760405162461bcd60e51b815260206004820152601760248201527f466163696c69747920646f6573206e6f7420657869737400000000000000000060448201526064016109f8565b60008281526010602052604090205481906001600160a01b03163314610d965760405162461bcd60e51b81526004016109f891906157e4565b60008151116131595760405162461bcd60e51b815260206004820152601960248201527f4461746120555249206d7573742062652070726f76696465640000000000000060448201526064016109f8565b816001600160a01b0316836001600160a01b031614156132ad5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016109f8565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613325848484612e23565b61333184848484613b79565b611fcb5760405162461bcd60e51b81526004016109f8906157f7565b606061335882612a21565b6133be5760405162461bcd60e51b815260206004820152603160248201527f45524337323155524953746f726167653a2055524920717565727920666f72206044820152703737b732bc34b9ba32b73a103a37b5b2b760791b60648201526084016109f8565b600082815260086020526040812080546133d7906159a5565b80601f0160208091040260200160405190810160405280929190818152602001828054613403906159a5565b80156134505780601f1061342557610100808354040283529160200191613450565b820191906000526020600020905b81548152906001019060200180831161343357829003601f168201915b50505050509050600061346e60408051602081019091526000815290565b9050805160001415613481575092915050565b8151156134b357808260405160200161349b9291906152ad565b60405160208183030381529060405292505050919050565b61129d84613c83565b6000806135407fe14fce867d3bcfe3e7c779de069d9e179b67b9288baf649805c61c495483896b84600001518560200151866040015160405160200161352594939291909384526001600160a01b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613d5b565b9050600080613553838660600151613da9565b9092509050600081600481111561356c5761356c615a3b565b148015613585575084516001600160a01b038381169116145b6135c25760405162461bcd60e51b815260206004820152600e60248201526d213937b5b2b7103b37bab1b432b960911b60448201526064016109f8565b509392505050565b60008281526012602052604090206002015483111561363c5760405162461bcd60e51b815260206004820152602860248201527f576974686472617720616d6f756e74206e6f7420616c6c6f777320696e207468604482015267697320737461746560c01b60648201526084016109f8565b6136498585858585613e19565b5050505050565b6000828152602081815260408083206001600160a01b0387168452825280832084845290915281208054349283929161368a908490615917565b9091555050600082815260016020908152604091829020805460ff1916905581518381529081018590529081018390526001600160a01b038516907f4eef3d1efb11f00508d9b7bb632ddcfa6da9d7105bd39f404bdd7362e6c59dbc90606001613142565b6000818152601160205260408120815b8154811015613765576012600083838154811061371e5761371e615a67565b6000918252602080832090910154835282019290925260400190206003015460ff1615613753578261374f816159e0565b9350505b8061375d816159e0565b9150506136ff565b5050919050565b60006001600160e01b031982166380ac58cd60e01b148061379d57506001600160e01b03198216635b5e139f60e01b145b80610b6557506301ffc9a760e01b6001600160e01b0319831614610b65565b6000828152602081815260408083206001600160a01b0388168452825280832084845282528083205460019283905292205460ff16600281111561380257613802615a3b565b146138635760405162461bcd60e51b815260206004820152602b60248201527f436f6d706c657465207769746864726177206e6f7420616c6c6f77656420696e60448201526a207468697320737461746560a81b60648201526084016109f8565b6000838152602081815260408083206001600160a01b03891684528252808320858452825280832083905560019091529020805460ff191660021790558015613649576138b96001600160a01b03851682613a20565b60408051828152602081018590529081018390526001600160a01b0380861691908716907f89eeb38ad2da123e4b3662ad415c1856733f76deaccee072a5234ab427ffdb70906060015b60405180910390a35050505050565b61391c8383613f5d565b6139296000848484613b79565b610d965760405162461bcd60e51b81526004016109f8906157f7565b60606139508561409c565b848461395b85614199565b60405160200161396e9493929190615470565b6040516020818303038152906040529050949350505050565b606061399286614199565b61399b86614199565b6139a48661409c565b6139ad8661409c565b6139b68661409c565b6040516020016139ca9594939291906152dc565b604051602081830303815290604052905095945050505050565b60606139ef826141d4565b6040516020016139ff91906155c6565b6040516020818303038152906040529050919050565b610d96838383614327565b80471015613a705760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016109f8565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613abd576040519150601f19603f3d011682016040523d82523d6000602084013e613ac2565b606091505b5050905080610d965760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016109f8565b613b42816143df565b60008181526008602052604090208054613b5b906159a5565b15905061315957600081815260086020526040812061315991614c06565b60006001600160a01b0384163b15613c7b57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290613bbd90339089908890889060040161560b565b602060405180830381600087803b158015613bd757600080fd5b505af1925050508015613c07575060408051601f3d908101601f19168201909252613c0491810190615068565b60015b613c61573d808015613c35576040519150601f19603f3d011682016040523d82523d6000602084013e613c3a565b606091505b508051613c595760405162461bcd60e51b81526004016109f8906157f7565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061129d565b50600161129d565b6060613c8e82612a21565b613cf25760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b60648201526084016109f8565b6000613d0960408051602081019091526000815290565b90506000815111613d295760405180602001604052806000815250613d54565b80613d3384614486565b604051602001613d449291906152ad565b6040516020818303038152906040525b9392505050565b6000610b65613d68614583565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600080825160411415613de05760208301516040840151606085015160001a613dd4878285856146aa565b94509450505050613e12565b825160401415613e0a5760208301516040840151613dff868383614797565b935093505050613e12565b506000905060025b9250929050565b6000828152602081815260408083206001600160a01b03891684528252808320848452909152902054831115613e865760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b60448201526064016109f8565b6000828152602081815260408083206001600160a01b03891684528252808320848452909152902054613eba908490615962565b6000838152602081815260408083206001600160a01b038a1684528252808320858452825280832093909355600190819052919020805460ff191682800217905550613f0f6001600160a01b03851684613a20565b60408051848152602081018490529081018290526001600160a01b0380861691908716907f89eeb38ad2da123e4b3662ad415c1856733f76deaccee072a5234ab427ffdb7090606001613903565b6001600160a01b038216613fb35760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016109f8565b613fbc81612a21565b156140095760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016109f8565b61401560008383613a15565b6001600160a01b038216600090815260056020526040812080546001929061403e908490615917565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060816140c05750506040805180820190915260018152600360fc1b602082015290565b8160005b81156140ea57806140d4816159e0565b91506140e39050600a8361592f565b91506140c4565b6000816001600160401b0381111561410457614104615a7d565b6040519080825280601f01601f19166020018201604052801561412e576020820181803683370190505b5090505b841561129d57614143600183615962565b9150614150600a866159fb565b61415b906030615917565b60f81b81838151811061417057614170615a67565b60200101906001600160f81b031916908160001a905350614192600a8661592f565b9450614132565b60606141a4826147d0565b6141b1608084901b6147d0565b60405161060f60f31b6020820152602281019290925260428201526062016139ff565b60608151600014156141f457505060408051602081019091526000815290565b6000604051806060016040528060408152602001615acc60409139905060006003845160026142239190615917565b61422d919061592f565b614238906004615943565b6001600160401b0381111561424f5761424f615a7d565b6040519080825280601f01601f191660200182016040528015614279576020820181803683370190505b509050600182016020820185865187015b808210156142e5576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f811685015184535060018301925061428a565b505060038651066001811461430157600281146143145761431c565b603d6001830353603d600283035361431c565b603d60018303535b509195945050505050565b6001600160a01b0383166143825761437d81600b80546000838152600c60205260408120829055600182018355919091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90155565b6143a5565b816001600160a01b0316836001600160a01b0316146143a5576143a58382614982565b6001600160a01b0382166143bc57610d9681614a1f565b826001600160a01b0316826001600160a01b031614610d9657610d968282614ace565b60006143ea82611b09565b90506143f881600084613a15565b614403600083612a3e565b6001600160a01b038116600090815260056020526040812080546001929061442c908490615962565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6060816144aa5750506040805180820190915260018152600360fc1b602082015290565b8160005b81156144d457806144be816159e0565b91506144cd9050600a8361592f565b91506144ae565b6000816001600160401b038111156144ee576144ee615a7d565b6040519080825280601f01601f191660200182016040528015614518576020820181803683370190505b5090505b841561129d5761452d600183615962565b915061453a600a866159fb565b614545906030615917565b60f81b81838151811061455a5761455a615a67565b60200101906001600160f81b031916908160001a90535061457c600a8661592f565b945061451c565b6000306001600160a01b037f0000000000000000000000000e21cfd7afaf4fa3ab6c4d40ffacc529a4799ba3161480156145dc57507f000000000000000000000000000000000000000000000000000000000000004d46145b1561460657507f8a333cfe82af8db58073263349e52790cdeb6bebec54e734496c287a79a0031590565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f526d3a31e9815659507c0a778a035a56918c23c988ebdbc4e8068d068c9d3b2e828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156146e1575060009050600361478e565b8460ff16601b141580156146f957508460ff16601c14155b1561470a575060009050600461478e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561475e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166147875760006001925092505061478e565b9150600090505b94509492505050565b6000806001600160ff1b038316816147b460ff86901c601b615917565b90506147c2878288856146aa565b935093505050935093915050565b7aff00000000000000ff00000000000000ff00000000000000ff00006bffffffff0000000000000000604083901c90811663ffffffff60c01b84161760201c63ffffffff60601b919091166001600160e01b031984161717601081901c9182167eff00000000000000ff00000000000000ff00000000000000ff000000000000821617600890811c7bff00000000000000ff00000000000000ff00000000000000ff000000939093167fff00000000000000ff00000000000000ff00000000000000ff000000000000009290921691909117919091179081901c7e0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f167f0f000f000f000f000f000f000f000f000f000f000f000f000f000f000f000f00600492831c16179061491e827f0606060606060606060606060606060606060606060606060606060606060606615917565b901c7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f16600761494e9190615943565b614978827f3030303030303030303030303030303030303030303030303030303030303030615917565b610b659190615917565b6000600161498f84611c43565b6149999190615962565b6000838152600a60205260409020549091508082146149ec576001600160a01b03841660009081526009602090815260408083208584528252808320548484528184208190558352600a90915290208190555b506000918252600a602090815260408084208490556001600160a01b039094168352600981528383209183525290812055565b600b54600090614a3190600190615962565b6000838152600c6020526040812054600b8054939450909284908110614a5957614a59615a67565b9060005260206000200154905080600b8381548110614a7a57614a7a615a67565b6000918252602080832090910192909255828152600c9091526040808220849055858252812055600b805480614ab257614ab2615a51565b6001900381819060005260206000200160009055905550505050565b6000614ad983611c43565b6001600160a01b0390931660009081526009602090815260408083208684528252808320859055938252600a9052919091209190915550565b828054614b1e906159a5565b90600052602060002090601f016020900481019282614b405760008555614b86565b82601f10614b595782800160ff19823516178555614b86565b82800160010185558215614b86579182015b82811115614b86578235825591602001919060010190614b6b565b506129f8929150614c3c565b828054614b9e906159a5565b90600052602060002090601f016020900481019282614bc05760008555614b86565b82601f10614bd957805160ff1916838001178555614b86565b82800160010185558215614b86579182015b82811115614b86578251825591602001919060010190614beb565b508054614c12906159a5565b6000825580601f10614c22575050565b601f01602090049060005260206000209081019061315991905b5b808211156129f85760008155600101614c3d565b80356001600160a01b0381168114614c6857600080fd5b919050565b80358015158114614c6857600080fd5b600082601f830112614c8e57600080fd5b81356001600160401b0380821115614ca857614ca8615a7d565b604051601f8301601f19908116603f01168101908282118183101715614cd057614cd0615a7d565b81604052838152866020858801011115614ce957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008083601f840112614d1b57600080fd5b5081356001600160401b03811115614d3257600080fd5b602083019150836020828501011115613e1257600080fd5b600060208284031215614d5c57600080fd5b613d5482614c51565b60008060408385031215614d7857600080fd5b614d8183614c51565b9150614d8f60208401614c51565b90509250929050565b600080600060608486031215614dad57600080fd5b614db684614c51565b9250614dc460208501614c51565b9150604084013590509250925092565b60008060008060808587031215614dea57600080fd5b614df385614c51565b9350614e0160208601614c51565b92506040850135915060608501356001600160401b03811115614e2357600080fd5b614e2f87828801614c7d565b91505092959194509250565b60008060408385031215614e4e57600080fd5b614e5783614c51565b9150614d8f60208401614c6d565b600080600060608486031215614e7a57600080fd5b614e8384614c51565b95602085013595506040909401359392505050565b60008060408385031215614eab57600080fd5b614eb483614c51565b946020939093013593505050565b600060208284031215614ed457600080fd5b5035919050565b60008060408385031215614eee57600080fd5b82359150614d8f60208401614c51565b60008060408385031215614f1157600080fd5b82359150602083013560038110614f2757600080fd5b809150509250929050565b600080600060408486031215614f4757600080fd5b8335925060208401356001600160401b03811115614f6457600080fd5b614f7086828701614d09565b9497909650939450505050565b600080600060608486031215614f9257600080fd5b505081359360208301359350604090920135919050565b60008060008060008060a08789031215614fc257600080fd5b863595506020870135945060408701359350614fe060608801614c6d565b925060808701356001600160401b03811115614ffb57600080fd5b61500789828a01614d09565b979a9699509497509295939492505050565b6000806000806080858703121561502f57600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561505d57600080fd5b8135613d5481615a93565b60006020828403121561507a57600080fd5b8151613d5481615a93565b60008060006040848603121561509a57600080fd5b83356001600160401b038111156150b057600080fd5b6150bc86828701614d09565b90945092506150cf905060208501614c6d565b90509250925092565b600080600080606085870312156150ee57600080fd5b84356001600160401b0381111561510457600080fd5b61511087828801614d09565b9095509350615123905060208601614c6d565b915061513160408601614c51565b905092959194509250565b6000806040838503121561514f57600080fd5b8235915060208301356001600160401b038082111561516d57600080fd5b908401906080828703121561518157600080fd5b60405160808101818110838211171561519c5761519c615a7d565b6040526151a883614c51565b81526151b660208401614c51565b6020820152604083013560408201526060830135828111156151d757600080fd5b6151e388828601614c7d565b6060830152508093505050509250929050565b6000815180845261520e816020860160208601615979565b601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6000815161525d818560208601615979565b9290920192915050565b6bffffffffffffffffffffffff198460601b168152818360148301376000910160140190815292915050565b838152818360208301376000910160200190815292915050565b600083516152bf818460208801615979565b8351908301906152d3818360208801615979565b01949350505050565b7f2261747472696275746573223a5b7b2274726169745f74797065223a2266616381527134b634ba3ca4b21116113b30b63ab2911d1160711b60208201526000865161532f816032850160208b01615979565b7f227d2c7b2274726169745f74797065223a2273706163654964222c2276616c756032918401918201526332911d1160e11b60528201528651615379816056840160208b01615979565b7f227d2c7b2274726169745f74797065223a227374617274446179222c2276616c60569290910191820152643ab2911d1160d91b607682015285516153c581607b840160208a01615979565b7f227d2c7b2274726169745f74797065223a226e756d6265724f6644617973222c607b929091019182015268113b30b63ab2911d1160b91b609b82015261546461545561544f61541860a485018961524b565b7f227d2c7b2274726169745f74797065223a227175616e74697479222c2276616c8152643ab2911d1160d91b602082015260250190565b8661524b565b62227d5d60e81b815260030190565b98975050505050505050565b72226e616d65223a2253746179546f6b656e202360681b8152845160009061549f816013850160208a01615979565b7f222c226465736372697074696f6e223a2253746179206174206c6f6467696e6760139184019182015273103330b1b4b634ba3c91161134b6b0b3b2911d1160611b603382015285516154f9816047840160208a01615979565b7111161132bc3a32b93730b62fbab936111d1160711b60479290910191820152845161552c816059840160208901615979565b6573706163652f60d01b60599290910191820152835161555381605f840160208801615979565b601160f91b605f92909101918201526060019695505050505050565b607b60f81b81526000835161558b816001850160208801615979565b600b60fa1b60019184019182015283516155ac816002840160208801615979565b607d60f81b60029290910191820152600301949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516155fe81601d850160208701615979565b91909101601d0192915050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061563e908301846151f6565b9695505050505050565b600060018060a01b0380881683528615156020840152851515604084015260a0606084015261567a60a08401866151f6565b91508084166080840152509695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612157578351835292840192918401916001016156ab565b84151581526001600160a01b0384166020820152821515604082015260806060820181905260009061563e908301846151f6565b8615158152856020820152846040820152836060820152821515608082015260c060a0820152600061546460c08301846151f6565b878152866020820152856040820152846060820152831515608082015260c060a08201526000612ca560c083018486615222565b83815260406020820152600061577e604083018486615222565b95945050505050565b8681528560208201528460408201528315156060820152821515608082015260c060a0820152600061546460c08301846151f6565b60208101600383106157de57634e487b7160e01b600052602160045260246000fd5b91905290565b602081526000613d5460208301846151f6565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f6e6c79206c6f6467696e6720666163696c697479206f776e657220697320616040820152651b1b1bddd95960d21b606082015260800190565b6020808252601b908201527f4f6e6c79207370616365206f776e657220697320616c6c6f7765640000000000604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b6000821982111561592a5761592a615a0f565b500190565b60008261593e5761593e615a25565b500490565b600081600019048311821515161561595d5761595d615a0f565b500290565b60008282101561597457615974615a0f565b500390565b60005b8381101561599457818101518382015260200161597c565b83811115611fcb5750506000910152565b600181811c908216806159b957607f821691505b602082108114156159da57634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156159f4576159f4615a0f565b5060010190565b600082615a0a57615a0a615a25565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b03198116811461315957600080fdfe4f6e6c7920666163696c697479206f776e6572206d617920616464205370616365734142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f68747470733a2f2f626166796265696767376d7777706e6e6d366d6d6b3374777863346172697a6f796336696a6e617965337064636977636f6868656f37786937686d2e697066732e647765622e6c696e6b2f746f6b656e2d696d6167652e706e67a2646970667358221220701949743df2e1d7092f946646e5c1cecd46d4e618b8c5d58c02647da652bbe564736f6c63430008070033