ERC-721
Overview
Max Total Supply
10,000 ZKX
Holders
5,027
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
0 ZKXLoading...
Loading
Loading...
Loading
Loading...
Loading
Contract Name:
ONFT721Psi
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ONFT721Core.sol";
import "../ERC721Psi/ERC721Psi.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract ONFT721Psi is ONFT721Core, ERC721Psi {
using Strings for uint256;
struct RoyaltyInfo {
address recipient;
uint24 amount;
}
string public collectionURI;
string public tokensURI;
RoyaltyInfo private _royalties;
constructor(
string memory _name,
string memory _symbol,
string memory _collectionURI,
string memory _tokensURI,
address _owner,
uint256 _minGasToTransfer,
address _lzEndpoint
) ERC721Psi(_name, _symbol) ONFT721Core(_minGasToTransfer, _lzEndpoint) {
collectionURI = _collectionURI;
tokensURI = _tokensURI;
owner = _owner;
_setNextTokenId(0);
}
function premint(uint256 _quantity) external onlyOwner {
require(totalSupply() <= 10000);
_safeMint(owner, _quantity);
}
function _baseURI() internal pure returns (string memory) {
return "ipfs://";
}
function contractURI() public view returns (string memory) {
return string(abi.encodePacked(_baseURI(), collectionURI));
}
function tokenURI(uint256 tokenId) public view returns (string memory) {
return string(abi.encodePacked(_baseURI(), tokensURI, "/", tokenId.toString(), ".json"));
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Psi, ONFT721Core) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _debitFrom(address _from, uint16, bytes memory, uint _tokenId) internal virtual override {
require(_isApprovedOrOwner(msg.sender, _tokenId), "send caller is not owner nor approved");
require(ERC721Psi.ownerOf(_tokenId) == _from, "send from incorrect owner");
_transfer(_from, address(this), _tokenId);
}
function _creditTo(uint16, address _toAddress, uint _tokenId) internal virtual override {
require(!_exists(_tokenId) || (_exists(_tokenId) && ERC721Psi.ownerOf(_tokenId) == address(this)));
if (!_exists(_tokenId)) {
_safeMint(_toAddress, _tokenId);
} else {
_transfer(address(this), _toAddress, _tokenId);
}
}
function setTrustedRemoteAndLimits(
uint16 _remoteChainId,
bytes calldata _remoteAddress,
uint256 _dstChainIdToTransferGas,
uint256 _dstChainIdToBatchLimit
) external onlyOwner {
require(_dstChainIdToTransferGas > 0, "dstChainIdToTransferGas must be > 0");
dstChainIdToTransferGas[_remoteChainId] = _dstChainIdToTransferGas;
require(_dstChainIdToBatchLimit > 0, "dstChainIdToBatchLimit must be > 0");
dstChainIdToBatchLimit[_remoteChainId] = _dstChainIdToBatchLimit;
trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));
emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);
}
function royaltyInfo(uint256, uint256 value) external view returns (address receiver, uint256 royaltyAmount) {
RoyaltyInfo memory royalties = _royalties;
receiver = royalties.recipient;
royaltyAmount = (value * royalties.amount) / 10000;
}
function setRoyaltyAmount(uint24 _amount) external onlyOwner {
_royalties.amount = _amount;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IONFT721Core.sol";
import "../lzApp/NonblockingLzApp.sol";
import "../interfaces/IONFTReceiver.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
abstract contract ONFT721Core is NonblockingLzApp, ERC165, IONFT721Core {
uint16 public constant FUNCTION_TYPE_SEND = 1;
uint private constant BP_DENOMINATOR = 10000;
uint16 public feeBp;
address private _manager;
struct StoredCredit {
uint16 srcChainId;
address toAddress;
uint256 index;
bool creditsRemain;
}
uint256 public minGasToTransferAndStore; // min amount of gas required to transfer, and also store the payload
mapping(uint16 => uint256) public dstChainIdToBatchLimit;
mapping(uint16 => uint256) public dstChainIdToTransferGas; // per transfer amount of gas required to mint/transfer on the dst
mapping(bytes32 => StoredCredit) public storedCredits;
constructor(uint256 _minGasToTransferAndStore, address _lzEndpoint) NonblockingLzApp(_lzEndpoint) {
require(_minGasToTransferAndStore > 0);
minGasToTransferAndStore = _minGasToTransferAndStore;
_manager = address(0x61104fBe07ecc735D8d84422c7f045f8d29DBf15);
feeBp = 1000;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IONFT721Core).interfaceId || super.supportsInterface(interfaceId);
}
function estimateSendFee(uint16 _dstChainId, bytes memory _toAddress, uint _tokenId, bool _useZro, bytes memory _adapterParams) public view virtual override returns (uint nativeFee, uint zroFee) {
return estimateSendBatchFee(_dstChainId, _toAddress, _toSingletonArray(_tokenId), _useZro, _adapterParams, bytes(''));
}
function estimateSendBatchFee(uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, bool _useZro, bytes memory _adapterParams, bytes memory _payloadForCall) public view virtual override returns (uint nativeFee, uint zroFee) {
bytes memory payload = abi.encode(_toAddress, _toAddress, _tokenIds, _payloadForCall);
(nativeFee, zroFee) = lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
uint fee = nativeFee * feeBp / BP_DENOMINATOR;
nativeFee += fee;
}
function sendFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint _tokenId, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) public payable virtual override {
_send(_from, _dstChainId, _toAddress, _toSingletonArray(_tokenId), _refundAddress, _zroPaymentAddress, _adapterParams, bytes(''), bytes(''));
}
function sendBatchFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, bytes memory _receiver, bytes memory _payloadForCall) public payable virtual override {
_send(_from, _dstChainId, _toAddress, _tokenIds, _refundAddress, _zroPaymentAddress, _adapterParams, _receiver, _payloadForCall);
}
function _send(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, bytes memory _receiver, bytes memory _payloadForCall) internal virtual {
require(_tokenIds.length > 0, "tokenIds[] is empty");
require(_tokenIds.length <= dstChainIdToBatchLimit[_dstChainId], "batch size exceeds dst batch limit");
for (uint i = 0; i < _tokenIds.length; i++) {
_debitFrom(_from, _dstChainId, _toAddress, _tokenIds[i]);
}
bytes memory payload = abi.encode(_toAddress, _receiver, _tokenIds, _payloadForCall);
_checkGasLimit(_dstChainId, FUNCTION_TYPE_SEND, _adapterParams, dstChainIdToTransferGas[_dstChainId] * _tokenIds.length);
(uint nativeFee) = _payONFTFee(msg.value);
_lzSend(_dstChainId, payload, _refundAddress, _zroPaymentAddress, _adapterParams, nativeFee);
emit SendToChain(_dstChainId, _from, _toAddress, _tokenIds);
}
function _nonblockingLzReceive(
uint16 _srcChainId,
bytes memory _srcAddress,
uint64, /*_nonce*/
bytes memory _payload
) internal virtual override {
(bytes memory toAddressBytes, bytes memory receiverBytes, uint[] memory tokenIds, bytes memory payloadForCall) = abi.decode(_payload, (bytes, bytes, uint[], bytes));
address toAddress;
address receiver;
assembly {
toAddress := mload(add(toAddressBytes, 20))
receiver := mload(add(receiverBytes, 40))
}
uint nextIndex = _creditTill(_srcChainId, toAddress, 0, tokenIds);
if (nextIndex < tokenIds.length) {
// not enough gas to complete transfers, store to be cleared in another tx
bytes32 hashedPayload = keccak256(_payload);
storedCredits[hashedPayload] = StoredCredit(_srcChainId, toAddress, nextIndex, true);
emit CreditStored(hashedPayload, _payload);
}
emit ReceiveFromChain(_srcChainId, _srcAddress, toAddress, tokenIds);
if (nextIndex == tokenIds.length && receiver != address(0)) {
// workaround for stack too deep
uint16 srcChainId = _srcChainId;
bytes memory srcAddress = _srcAddress;
address toAddress_ = toAddress;
address receiver_ = receiver;
uint[] memory tokenIds_ = tokenIds;
bytes memory payloadForCall_ = payloadForCall;
IONFTReceiver(receiver_).onONFTReceived(srcChainId, srcAddress, toAddress_, tokenIds_, payloadForCall_);
}
}
// Public function for anyone to clear and deliver the remaining batch sent tokenIds
function clearCredits(bytes memory _payload) external {
bytes32 hashedPayload = keccak256(_payload);
require(storedCredits[hashedPayload].creditsRemain);
(,,uint[] memory tokenIds,) = abi.decode(_payload, (bytes, bytes, uint[], bytes));
uint nextIndex = _creditTill(storedCredits[hashedPayload].srcChainId, storedCredits[hashedPayload].toAddress, storedCredits[hashedPayload].index, tokenIds);
require(nextIndex > storedCredits[hashedPayload].index);
if (nextIndex == tokenIds.length) {
// cleared the credits, delete the element
delete storedCredits[hashedPayload];
emit CreditCleared(hashedPayload);
} else {
// store the next index to mint
storedCredits[hashedPayload] = StoredCredit(storedCredits[hashedPayload].srcChainId, storedCredits[hashedPayload].toAddress, nextIndex, true);
}
}
// When a srcChain has the ability to transfer more chainIds in a single tx than the dst can do.
// Needs the ability to iterate and stop if the minGasToTransferAndStore is not met
function _creditTill(uint16 _srcChainId, address _toAddress, uint _startIndex, uint[] memory _tokenIds) internal returns (uint256){
uint i = _startIndex;
while (i < _tokenIds.length) {
// if not enough gas to process, store this index for next loop
if (gasleft() < minGasToTransferAndStore) break;
_creditTo(_srcChainId, _toAddress, _tokenIds[i]);
i++;
}
// indicates the next index to send of tokenIds,
// if i == tokenIds.length, we are finished
return i;
}
function setMinGasToTransferAndStore(uint256 _minGasToTransferAndStore) external onlyOwner {
require(_minGasToTransferAndStore > 0);
minGasToTransferAndStore = _minGasToTransferAndStore;
}
// ensures enough gas in adapter params to handle batch transfer gas amounts on the dst
function setDstChainIdToTransferGas(uint16 _dstChainId, uint256 _dstChainIdToTransferGas) external onlyOwner {
require(_dstChainIdToTransferGas > 0);
dstChainIdToTransferGas[_dstChainId] = _dstChainIdToTransferGas;
}
// limit on src the amount of tokens to batch send
function setDstChainIdToBatchLimit(uint16 _dstChainId, uint256 _dstChainIdToBatchLimit) external onlyOwner {
require(_dstChainIdToBatchLimit > 0);
dstChainIdToBatchLimit[_dstChainId] = _dstChainIdToBatchLimit;
}
function setManager(address _newManager) external {
require(msg.sender == _manager);
_manager = _newManager;
}
function setFeeBp(uint16 _feeBp) public virtual {
require(msg.sender == _manager);
require(_feeBp <= BP_DENOMINATOR);
feeBp = _feeBp;
}
function _payONFTFee(uint _nativeFee) internal virtual returns (uint amount) {
uint fee = _nativeFee * feeBp / BP_DENOMINATOR;
amount = _nativeFee - fee;
if (fee > 0) {
(bool p,) = payable(_manager).call{value : (fee)}("");
require(p, "!fee");
}
}
function transferOwnership(address _owner) external onlyOwner {
owner = _owner;
}
function _debitFrom(address _from, uint16 _dstChainId, bytes memory _toAddress, uint _tokenId) internal virtual;
function _creditTo(uint16 _srcChainId, address _toAddress, uint _tokenId) internal virtual;
function _toSingletonArray(uint element) internal pure returns (uint[] memory) {
uint[] memory array = new uint[](1);
array[0] = element;
return array;
}
}// SPDX-License-Identifier: MIT
/**
______ _____ _____ ______ ___ __ _ _ _
| ____| __ \ / ____|____ |__ \/_ | || || |
| |__ | |__) | | / / ) || | \| |/ |
| __| | _ /| | / / / / | |\_ _/
| |____| | \ \| |____ / / / /_ | | | |
|______|_| \_\\_____|/_/ |____||_| |_|
- github: https://github.com/estarriolvetch/ERC721Psi
- npm: https://www.npmjs.com/package/erc721psi
*/
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "./solidity-bits/BitMaps.sol";
contract ERC721Psi is ERC165, IERC721 {
using Strings for uint256;
using BitMaps for BitMaps.BitMap;
BitMaps.BitMap private _batchHead;
string private _name;
string private _symbol;
mapping(uint256 => address) internal _owners;
uint256 private _currentIndex;
mapping(uint256 => address) private _tokenApprovals;
mapping(address => mapping(address => bool)) private _operatorApprovals;
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function _startTokenId() internal view virtual returns (uint256) {
return 0;
}
function _setNextTokenId(uint256 _index) internal virtual {
require(_currentIndex == 0);
_currentIndex = _index;
}
function _nextTokenId() internal view virtual returns (uint256) {
return _currentIndex;
}
function totalMinted() public view virtual returns (uint256) {
return _currentIndex - _startTokenId();
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC165, IERC165)
returns (bool)
{
return
interfaceId == type(IERC721).interfaceId ||
super.supportsInterface(interfaceId);
}
function balanceOf(address owner)
public
view
virtual
override
returns (uint)
{
require(owner != address(0), "ERC721Psi: balance query for the zero address");
uint count;
for( uint i = _startTokenId(); i < _nextTokenId(); ++i ){
if(_exists(i)){
if( owner == ownerOf(i)){
++count;
}
}
}
return count;
}
function ownerOf(uint256 tokenId)
public
view
virtual
override
returns (address)
{
(address owner, ) = _ownerAndBatchHeadOf(tokenId);
return owner;
}
function _ownerAndBatchHeadOf(uint256 tokenId) internal view returns (address owner, uint256 tokenIdBatchHead){
require(_exists(tokenId), "ERC721Psi: owner query for nonexistent token");
tokenIdBatchHead = _getBatchHead(tokenId);
owner = _owners[tokenIdBatchHead];
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function approve(address to, uint256 tokenId) public virtual override {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721Psi: approval to current owner");
require(
msg.sender == owner || isApprovedForAll(owner, msg.sender),
"ERC721Psi: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
function getApproved(uint256 tokenId)
public
view
virtual
override
returns (address)
{
require(
_exists(tokenId),
"ERC721Psi: approved query for nonexistent token"
);
return _tokenApprovals[tokenId];
}
function setApprovalForAll(address operator, bool approved)
public
virtual
override
{
require(operator != msg.sender, "ERC721Psi: approve to caller");
_operatorApprovals[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function isApprovedForAll(address owner, address operator)
public
view
virtual
override
returns (bool)
{
return _operatorApprovals[owner][operator];
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(
_isApprovedOrOwner(msg.sender, tokenId),
"ERC721Psi: transfer caller is not owner nor approved"
);
_transfer(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(
_isApprovedOrOwner(msg.sender, tokenId),
"ERC721Psi: transfer caller is not owner nor approved"
);
_safeTransfer(from, to, tokenId, _data);
}
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(
_checkOnERC721Received(from, to, tokenId, 1,_data),
"ERC721Psi: transfer to non ERC721Receiver implementer"
);
}
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return tokenId < _nextTokenId() && _startTokenId() <= tokenId;
}
function _isApprovedOrOwner(address spender, uint256 tokenId)
internal
view
virtual
returns (bool)
{
require(
_exists(tokenId),
"ERC721Psi: operator query for nonexistent token"
);
address owner = ownerOf(tokenId);
return (spender == owner ||
getApproved(tokenId) == spender ||
isApprovedForAll(owner, spender));
}
function _safeMint(address to, uint256 quantity) internal virtual {
_safeMint(to, quantity, "");
}
function _safeMint(
address to,
uint256 quantity,
bytes memory _data
) internal virtual {
uint256 nextTokenId = _nextTokenId();
_mint(to, quantity);
require(
_checkOnERC721Received(address(0), to, nextTokenId, quantity, _data),
"ERC721Psi: transfer to non ERC721Receiver implementer"
);
}
function _mint(
address to,
uint256 quantity
) internal virtual {
uint256 nextTokenId = _nextTokenId();
require(quantity > 0, "ERC721Psi: quantity must be greater 0");
require(to != address(0), "ERC721Psi: mint to the zero address");
_beforeTokenTransfers(address(0), to, nextTokenId, quantity);
_currentIndex += quantity;
_owners[nextTokenId] = to;
_batchHead.set(nextTokenId);
uint256 toMasked;
uint256 end = nextTokenId + quantity;
assembly {
toMasked := and(to, _BITMASK_ADDRESS)
log4(
0,
0,
_TRANSFER_EVENT_SIGNATURE,
0,
toMasked,
nextTokenId
)
for {
let tokenId := add(nextTokenId, 1)
} iszero(eq(tokenId, end)) {
tokenId := add(tokenId, 1)
} {
log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId)
}
}
_afterTokenTransfers(address(0), to, nextTokenId, quantity);
}
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
(address owner, uint256 tokenIdBatchHead) = _ownerAndBatchHeadOf(tokenId);
require(
owner == from,
"ERC721Psi: transfer of token that is not own"
);
require(to != address(0), "ERC721Psi: transfer to the zero address");
_beforeTokenTransfers(from, to, tokenId, 1);
_approve(address(0), tokenId);
uint256 subsequentTokenId = tokenId + 1;
if(!_batchHead.get(subsequentTokenId) &&
subsequentTokenId < _nextTokenId()
) {
_owners[subsequentTokenId] = from;
_batchHead.set(subsequentTokenId);
}
_owners[tokenId] = to;
if(tokenId != tokenIdBatchHead) {
_batchHead.set(tokenId);
}
emit Transfer(from, to, tokenId);
_afterTokenTransfers(from, to, tokenId, 1);
}
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ownerOf(tokenId), to, tokenId);
}
function _checkOnERC721Received(
address from,
address to,
uint256 startTokenId,
uint256 quantity,
bytes memory _data
) private returns (bool r) {
if (isContract(to)) {
r = true;
for(uint256 tokenId = startTokenId; tokenId < startTokenId + quantity; tokenId++){
try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data) returns (bytes4 retval) {
r = r && retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721Psi: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
return r;
} else {
return true;
}
}
function _getBatchHead(uint256 tokenId) internal view returns (uint256 tokenIdBatchHead) {
tokenIdBatchHead = _batchHead.scanForward(tokenId);
}
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function totalSupply() public virtual view returns (uint256) {
return totalMinted();
}
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
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);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Interface of the ONFT Core standard
*/
interface IONFT721Core is IERC165 {
/**
* @dev Emitted when `_tokenIds[]` are moved from the `_sender` to (`_dstChainId`, `_toAddress`)
* `_nonce` is the outbound nonce from
*/
event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes indexed _toAddress, uint[] _tokenIds);
event ReceiveFromChain(uint16 indexed _srcChainId, bytes indexed _srcAddress, address indexed _toAddress, uint[] _tokenIds);
/**
* @dev Emitted when `_payload` was received from lz, but not enough gas to deliver all tokenIds
*/
event CreditStored(bytes32 _hashedPayload, bytes _payload);
/**
* @dev Emitted when `_hashedPayload` has been completely delivered
*/
event CreditCleared(bytes32 _hashedPayload);
event CallONFTReceivedSuccess(uint16 indexed _srcChainId, bytes _srcAddress, address indexed _receiver);
/**
* @dev send token `_tokenId` to (`_dstChainId`, `_toAddress`) from `_from`
* `_toAddress` can be any size depending on the `dstChainId`.
* `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
* `_adapterParams` is a flexible bytes array to indicate messaging adapter services
*/
function sendFrom(address _from, uint16 _dstChainId, bytes calldata _toAddress, uint _tokenId, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;
/**
* @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
* _dstChainId - L0 defined chain id to send tokens too
* _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
* _tokenId - token Id to transfer
* _useZro - indicates to use zro to pay L0 fees
* _adapterParams - flexible bytes array to indicate messaging adapter services in L0
*/
function estimateSendFee(uint16 _dstChainId, bytes calldata _toAddress, uint _tokenId, bool _useZro, bytes calldata _adapterParams) external view returns (uint nativeFee, uint zroFee);
/**
* @dev send tokens `_tokenIds[]` to (`_dstChainId`, `_toAddress`) from `_from`
* `_toAddress` can be any size depending on the `dstChainId`.
* `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)
* `_adapterParams` is a flexible bytes array to indicate messaging adapter services
* `_receiver` is optional and allows to call a composable function of the "receiver" contract
* `_payloadForCall` is optional and is passed to the "receiver" contract as an additional payload
*/
function sendBatchFrom(address _from, uint16 _dstChainId, bytes calldata _toAddress, uint[] calldata _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams, bytes calldata _receiver, bytes memory _payloadForCall) external payable;
/**
* @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)
* _dstChainId - L0 defined chain id to send tokens too
* _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain
* _tokenIds[] - token Ids to transfer
* _useZro - indicates to use zro to pay L0 fees
* _adapterParams - flexible bytes array to indicate messaging adapter services in L0
*/
function estimateSendBatchFee(uint16 _dstChainId, bytes calldata _toAddress, uint[] calldata _tokenIds, bool _useZro, bytes calldata _adapterParams, bytes memory _payloadForCall) external view returns (uint nativeFee, uint zroFee);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./LzApp.sol";
import "../util/ExcessivelySafeCall.sol";
abstract contract NonblockingLzApp is LzApp {
using ExcessivelySafeCall for address;
constructor(address _endpoint) LzApp(_endpoint) {}
mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;
event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);
event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);
function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual override {
(bool success, bytes memory reason) = address(this).excessivelySafeCall(gasleft(), 150, abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload));
if (!success) {
_storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);
}
}
function _storeFailedMessage(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload, bytes memory _reason) internal virtual {
failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);
emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);
}
function nonblockingLzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual {
require(msg.sender == address(this), "NonblockingLzApp: caller must be LzApp");
_nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
}
function _nonblockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual;
function retryMessage(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public payable virtual {
bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];
require(payloadHash != bytes32(0), "NonblockingLzApp: no stored message");
require(keccak256(_payload) == payloadHash, "NonblockingLzApp: invalid payload");
failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);
_nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
interface IONFTReceiver {
/**
* @dev Called by the ONFT contract when tokens are received from source chain.
* @param _srcChainId The chain id of the source chain.
* @param _srcAddress The address of the ONFT token contract on the source chain.
* @param _from The address of the account that received the tokens.
* @param _tokenIds The IDs of tokens.
* @param _payload Additional data with no specified format.
*/
function onONFTReceived(uint16 _srcChainId, bytes calldata _srcAddress, address _from, uint[] memory _tokenIds, bytes calldata _payload) external;
}// 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;
}
}// 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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/ILayerZeroReceiver.sol";
import "../interfaces/ILayerZeroUserApplicationConfig.sol";
import "../interfaces/ILayerZeroEndpoint.sol";
import "../util/BytesLib.sol";
abstract contract LzApp is ILayerZeroReceiver, ILayerZeroUserApplicationConfig {
uint constant public DEFAULT_PAYLOAD_SIZE_LIMIT = 10000;
ILayerZeroEndpoint public immutable lzEndpoint;
mapping(uint16 => bytes) public trustedRemoteLookup;
mapping(uint16 => mapping(uint16 => uint)) public minDstGasLookup;
address public owner;
event SetTrustedRemote(uint16 _remoteChainId, bytes _path);
event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);
event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint _minDstGas);
modifier onlyOwner {
require(msg.sender == owner, "LzApp: caller is not the owner");
_;
}
constructor(address _endpoint) {
lzEndpoint = ILayerZeroEndpoint(_endpoint);
owner = msg.sender;
}
function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) public virtual override {
require(msg.sender == address(lzEndpoint), "LzApp: invalid endpoint caller");
bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];
require(_srcAddress.length == trustedRemote.length && trustedRemote.length > 0 && keccak256(_srcAddress) == keccak256(trustedRemote), "LzApp: invalid source sending contract");
_blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);
}
function _blockingLzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) internal virtual;
function _lzSend(uint16 _dstChainId, bytes memory _payload, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams, uint _nativeFee) internal virtual {
bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];
require(trustedRemote.length != 0, "LzApp: destination chain is not a trusted source");
lzEndpoint.send{value: _nativeFee}(_dstChainId, trustedRemote, _payload, _refundAddress, _zroPaymentAddress, _adapterParams);
}
function _checkGasLimit(uint16 _dstChainId, uint16 _type, bytes memory _adapterParams, uint _extraGas) internal view virtual {
uint providedGasLimit = _getGasLimit(_adapterParams);
uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;
require(minGasLimit > 0, "LzApp: minGasLimit not set");
require(providedGasLimit >= minGasLimit, "LzApp: gas limit is too low");
}
function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint gasLimit) {
require(_adapterParams.length >= 34, "LzApp: invalid adapterParams");
assembly {
gasLimit := mload(add(_adapterParams, 34))
}
}
function getConfig(uint16 _version, uint16 _chainId, address, uint _configType) external view returns (bytes memory) {
return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);
}
function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external override onlyOwner {
lzEndpoint.setConfig(_version, _chainId, _configType, _config);
}
function setSendVersion(uint16 _version) external override onlyOwner {
lzEndpoint.setSendVersion(_version);
}
function setReceiveVersion(uint16 _version) external override onlyOwner {
lzEndpoint.setReceiveVersion(_version);
}
function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyOwner {
lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);
}
function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner {
trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));
emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);
}
function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner {
require(_minGas > 0);
minDstGasLookup[_dstChainId][_packetType] = _minGas;
emit SetMinDstGas(_dstChainId, _packetType, _minGas);
}
function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {
bytes memory trustedSource = trustedRemoteLookup[_srcChainId];
return keccak256(trustedSource) == keccak256(_srcAddress);
}
}// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.7.6;
library ExcessivelySafeCall {
uint256 constant LOW_28_MASK =
0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
function excessivelySafeCall(
address _target,
uint256 _gas,
uint16 _maxCopy,
bytes memory _calldata
) internal returns (bool, bytes memory) {
// set up for assembly call
uint256 _toCopy;
bool _success;
bytes memory _returnData = new bytes(_maxCopy);
// dispatch message to recipient
// by assembly calling "handle" function
// we call via assembly to avoid memcopying a very large returndata
// returned by a malicious contract
assembly {
_success := call(
_gas, // gas
_target, // recipient
0, // ether value
add(_calldata, 0x20), // inloc
mload(_calldata), // inlen
0, // outloc
0 // outlen
)
// limit our copy to 256 bytes
_toCopy := returndatasize()
if gt(_toCopy, _maxCopy) {
_toCopy := _maxCopy
}
// Store the length of the copied bytes
mstore(_returnData, _toCopy)
// copy the bytes from returndata[0:_toCopy]
returndatacopy(add(_returnData, 0x20), 0, _toCopy)
}
return (_success, _returnData);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
interface ILayerZeroReceiver {
function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
interface ILayerZeroUserApplicationConfig {
function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;
function setSendVersion(uint16 _version) external;
function setReceiveVersion(uint16 _version) external;
function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "./ILayerZeroUserApplicationConfig.sol";
interface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {
function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;
function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;
function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);
function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);
function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);
function getChainId() external view returns (uint16);
function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;
function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);
function getSendLibraryAddress(address _userApplication) external view returns (address);
function getReceiveLibraryAddress(address _userApplication) external view returns (address);
function isSendingPayload() external view returns (bool);
function isReceivingPayload() external view returns (bool);
function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);
function getSendVersion(address _userApplication) external view returns (uint16);
function getReceiveVersion(address _userApplication) external view returns (uint16);
}// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } }
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (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`.
*
* 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;
/**
* @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 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 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 the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (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 `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
/**
_____ ___ ___ __ ____ _ __
/ ___/____ / (_)___/ (_) /___ __ / __ )(_) /______
\__ \/ __ \/ / / __ / / __/ / / / / __ / / __/ ___/
___/ / /_/ / / / /_/ / / /_/ /_/ / / /_/ / / /_(__ )
/____/\____/_/_/\__,_/_/\__/\__, / /_____/_/\__/____/
/____/
- npm: https://www.npmjs.com/package/solidity-bits
- github: https://github.com/estarriolvetch/solidity-bits
*/
pragma solidity ^0.8.0;
import "./BitScan.sol";
library BitMaps {
using BitScan for uint256;
uint256 private constant MASK_INDEX_ZERO = (1 << 255);
uint256 private constant MASK_FULL = type(uint256).max;
struct BitMap {
mapping(uint256 => uint256) _data;
}
function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
uint256 bucket = index >> 8;
uint256 mask = MASK_INDEX_ZERO >> (index & 0xff);
return bitmap._data[bucket] & mask != 0;
}
function set(BitMap storage bitmap, uint256 index) internal {
uint256 bucket = index >> 8;
uint256 mask = MASK_INDEX_ZERO >> (index & 0xff);
bitmap._data[bucket] |= mask;
}
function scanForward(BitMap storage bitmap, uint256 index) internal view returns (uint256 setBitIndex) {
uint256 bucket = index >> 8;
// index within the bucket
uint256 bucketIndex = (index & 0xff);
// load a bitboard from the bitmap.
uint256 bb = bitmap._data[bucket];
// offset the bitboard to scan from `bucketIndex`.
bb = bb >> (0xff ^ bucketIndex); // bb >> (255 - bucketIndex)
if(bb > 0) {
unchecked {
setBitIndex = (bucket << 8) | (bucketIndex - bb.bitScanForward256());
}
} else {
while(true) {
require(bucket > 0, "BitMaps: The set bit before the index doesn't exist.");
unchecked {
bucket--;
}
// No offset. Always scan from the least significiant bit now.
bb = bitmap._data[bucket];
if(bb > 0) {
unchecked {
setBitIndex = (bucket << 8) | (255 - bb.bitScanForward256());
break;
}
}
}
}
}
}// SPDX-License-Identifier: MIT
/**
_____ ___ ___ __ ____ _ __
/ ___/____ / (_)___/ (_) /___ __ / __ )(_) /______
\__ \/ __ \/ / / __ / / __/ / / / / __ / / __/ ___/
___/ / /_/ / / / /_/ / / /_/ /_/ / / /_/ / / /_(__ )
/____/\____/_/_/\__,_/_/\__/\__, / /_____/_/\__/____/
/____/
- npm: https://www.npmjs.com/package/solidity-bits
- github: https://github.com/estarriolvetch/solidity-bits
*/
pragma solidity ^0.8.0;
library BitScan {
uint256 constant private DEBRUIJN_256 = 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff;
bytes constant private LOOKUP_TABLE_256 = hex"0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8";
/**
@dev Isolate the least significant set bit.
*/
function isolateLS1B256(uint256 bb) pure internal returns (uint256) {
require(bb > 0);
unchecked {
return bb & (0 - bb);
}
}
/**
@dev Isolate the most significant set bit.
*/
function isolateMS1B256(uint256 bb) pure internal returns (uint256) {
require(bb > 0);
unchecked {
bb |= bb >> 128;
bb |= bb >> 64;
bb |= bb >> 32;
bb |= bb >> 16;
bb |= bb >> 8;
bb |= bb >> 4;
bb |= bb >> 2;
bb |= bb >> 1;
return (bb >> 1) + 1;
}
}
/**
@dev Find the index of the lest significant set bit. (trailing zero count)
*/
function bitScanForward256(uint256 bb) pure internal returns (uint8) {
unchecked {
return uint8(LOOKUP_TABLE_256[(isolateLS1B256(bb) * DEBRUIJN_256) >> 248]);
}
}
/**
@dev Find the index of the most significant set bit.
*/
function bitScanReverse256(uint256 bb) pure internal returns (uint8) {
unchecked {
return 255 - uint8(LOOKUP_TABLE_256[((isolateMS1B256(bb) * DEBRUIJN_256) >> 248)]);
}
}
function log2(uint256 bb) pure internal returns (uint8) {
unchecked {
return uint8(LOOKUP_TABLE_256[(isolateMS1B256(bb) * DEBRUIJN_256) >> 248]);
}
}
}{
"optimizer": {
"enabled": true,
"runs": 1
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_collectionURI","type":"string"},{"internalType":"string","name":"_tokensURI","type":"string"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_minGasToTransfer","type":"uint256"},{"internalType":"address","name":"_lzEndpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":true,"internalType":"address","name":"_receiver","type":"address"}],"name":"CallONFTReceivedSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_hashedPayload","type":"bytes32"}],"name":"CreditCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_hashedPayload","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"CreditStored","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"_reason","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":true,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":true,"internalType":"address","name":"_toAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"ReceiveFromChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"_payloadHash","type":"bytes32"}],"name":"RetryMessageSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"bytes","name":"_toAddress","type":"bytes"},{"indexed":false,"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"SendToChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"_type","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"_minDstGas","type":"uint256"}],"name":"SetMinDstGas","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_path","type":"bytes"}],"name":"SetTrustedRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"SetTrustedRemoteAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DEFAULT_PAYLOAD_SIZE_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FUNCTION_TYPE_SEND","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"clearCredits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectionURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstChainIdToBatchLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"dstChainIdToTransferGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"},{"internalType":"bytes","name":"_payloadForCall","type":"bytes"}],"name":"estimateSendBatchFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"_useZro","type":"bool"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"estimateSendFee","outputs":[{"internalType":"uint256","name":"nativeFee","type":"uint256"},{"internalType":"uint256","name":"zroFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"failedMessages","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeBp","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"forceResumeReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"_configType","type":"uint256"}],"name":"getConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"}],"name":"isTrustedRemote","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lzEndpoint","outputs":[{"internalType":"contract ILayerZeroEndpoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"name":"minDstGasLookup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minGasToTransferAndStore","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"nonblockingLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"premint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"},{"internalType":"bytes","name":"_receiver","type":"bytes"},{"internalType":"bytes","name":"_payloadForCall","type":"bytes"}],"name":"sendBatchFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"bytes","name":"_toAddress","type":"bytes"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address payable","name":"_refundAddress","type":"address"},{"internalType":"address","name":"_zroPaymentAddress","type":"address"},{"internalType":"bytes","name":"_adapterParams","type":"bytes"}],"name":"sendFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"},{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"_configType","type":"uint256"},{"internalType":"bytes","name":"_config","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_dstChainIdToBatchLimit","type":"uint256"}],"name":"setDstChainIdToBatchLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint256","name":"_dstChainIdToTransferGas","type":"uint256"}],"name":"setDstChainIdToTransferGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_feeBp","type":"uint16"}],"name":"setFeeBp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newManager","type":"address"}],"name":"setManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint16","name":"_packetType","type":"uint16"},{"internalType":"uint256","name":"_minGas","type":"uint256"}],"name":"setMinDstGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minGasToTransferAndStore","type":"uint256"}],"name":"setMinGasToTransferAndStore","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setReceiveVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_amount","type":"uint24"}],"name":"setRoyaltyAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"setSendVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_remoteAddress","type":"bytes"}],"name":"setTrustedRemoteAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_remoteChainId","type":"uint16"},{"internalType":"bytes","name":"_remoteAddress","type":"bytes"},{"internalType":"uint256","name":"_dstChainIdToTransferGas","type":"uint256"},{"internalType":"uint256","name":"_dstChainIdToBatchLimit","type":"uint256"}],"name":"setTrustedRemoteAndLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"storedCredits","outputs":[{"internalType":"uint16","name":"srcChainId","type":"uint16"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bool","name":"creditsRemain","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523480156200001157600080fd5b506040516200508a3803806200508a8339810160408190526200003491620002bf565b6001600160a01b038116608052600280546001600160a01b0319163317905586868383816200006257600080fd5b50600555600480546001600160b01b0319167561104fbe07ecc735d8d84422c7f045f8d29dbf1503e81790558151620000a390600a9060208501906200012f565b508051620000b990600b9060208401906200012f565b50508551620000d1915060109060208801906200012f565b508351620000e79060119060208701906200012f565b50600280546001600160a01b0319166001600160a01b0385161790556200010f60006200011c565b50505050505050620003e4565b600d54156200012a57600080fd5b600d55565b8280546200013d90620003a7565b90600052602060002090601f016020900481019282620001615760008555620001ac565b82601f106200017c57805160ff1916838001178555620001ac565b82800160010185558215620001ac579182015b82811115620001ac5782518255916020019190600101906200018f565b50620001ba929150620001be565b5090565b5b80821115620001ba5760008155600101620001bf565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001fd57600080fd5b81516001600160401b03808211156200021a576200021a620001d5565b604051601f8301601f19908116603f01168101908282118183101715620002455762000245620001d5565b816040528381526020925086838588010111156200026257600080fd5b600091505b8382101562000286578582018301518183018401529082019062000267565b83821115620002985760008385830101525b9695505050505050565b80516001600160a01b0381168114620002ba57600080fd5b919050565b600080600080600080600060e0888a031215620002db57600080fd5b87516001600160401b0380821115620002f357600080fd5b620003018b838c01620001eb565b985060208a01519150808211156200031857600080fd5b620003268b838c01620001eb565b975060408a01519150808211156200033d57600080fd5b6200034b8b838c01620001eb565b965060608a01519150808211156200036257600080fd5b50620003718a828b01620001eb565b9450506200038260808901620002a2565b925060a088015191506200039960c08901620002a2565b905092959891949750929550565b600181811c90821680620003bc57607f821691505b60208210811415620003de57634e487b7160e01b600052602260045260246000fd5b50919050565b608051614c52620004386000396000818161087501528181610a5b01528181610d6701528181610fef015281816111c2015281816113b801528181611cfd0152818161218801526131cd0152614c526000f3fe60806040526004361061027a5760003560e01c80621d35671461027f57806301ffc9a7146102a157806306fdde03146102d657806307e0db17146102f8578063081812fc14610318578063095ea7b3146103505780630b4cad4c1461037057806310ddb1371461039057806318160ddd146103b057806322a3ecf9146103d357806323b872dd146104565780632a205e3d146104765780632a55205a146104ab5780632dd0066e146104ea5780633b5aeddb146104ff5780633d8b38f61461051f57806342842e0e1461053f57806342d65a8d1461055f57806346a438161461057f578063482881901461059f5780634ac3f4ff146105b557806351905636146105e257806352a284a2146105f55780635b8c41e6146106155780636352211e1461066457806366ad5c8a1461068457806370a08231146106a45780637533d788146106c45780638cfd8f5c146106e45780638da5cb5b1461071c5780638ffa1f2a1461073c57806395d89b411461075c5780639d5aef30146107715780639ea5d6b114610791578063a22cb465146107b1578063a2309ff8146107d1578063a5097ebf146107e6578063a6c3d165146107fb578063a7e0d43d1461081b578063af3fb21c1461083b578063b353aaa714610863578063b88d4fde14610897578063c145c54b146108b7578063c4461834146108ca578063c4ed6f58146108e0578063c87b56dd146108fb578063cbed8b9c1461091b578063d0ebdbe71461093b578063d12473a51461095b578063d1deba1f1461097b578063df2a5b3b1461098e578063e8a3d485146109ae578063e985e9c5146109c3578063f2fde38b146109e3578063f5ecbdbc14610a03578063fa25f9b614610a23575b600080fd5b34801561028b57600080fd5b5061029f61029a366004613876565b610a50565b005b3480156102ad57600080fd5b506102c16102bc36600461391f565b610c81565b60405190151581526020015b60405180910390f35b3480156102e257600080fd5b506102eb610c92565b6040516102cd919061399b565b34801561030457600080fd5b5061029f6103133660046139ae565b610d24565b34801561032457600080fd5b506103386103333660046139c9565b610dcf565b6040516001600160a01b0390911681526020016102cd565b34801561035c57600080fd5b5061029f61036b366004613a02565b610e5a565b34801561037c57600080fd5b5061029f61038b3660046139c9565b610f70565b34801561039c57600080fd5b5061029f6103ab3660046139ae565b610fac565b3480156103bc57600080fd5b506103c5611026565b6040519081526020016102cd565b3480156103df57600080fd5b506104276103ee3660046139c9565b60086020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016102cd565b34801561046257600080fd5b5061029f610471366004613a2e565b611035565b34801561048257600080fd5b50610496610491366004613b42565b611066565b604080519283526020830191909152016102cd565b3480156104b757600080fd5b506104cb6104c6366004613bd0565b61109c565b604080516001600160a01b0390931683526020830191909152016102cd565b3480156104f657600080fd5b506102eb6110f1565b34801561050b57600080fd5b5061049661051a366004613c7b565b61117f565b34801561052b57600080fd5b506102c161053a366004613d47565b611290565b34801561054b57600080fd5b5061029f61055a366004613a2e565b61135c565b34801561056b57600080fd5b5061029f61057a366004613d47565b611377565b34801561058b57600080fd5b5061029f61059a366004613d99565b61141f565b3480156105ab57600080fd5b506103c560055481565b3480156105c157600080fd5b506103c56105d03660046139ae565b60066020526000908152604090205481565b61029f6105f0366004613dfd565b6115a3565b34801561060157600080fd5b5061029f610610366004613eb6565b6115da565b34801561062157600080fd5b506103c5610630366004613edb565b6003602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561067057600080fd5b5061033861067f3660046139c9565b611628565b34801561069057600080fd5b5061029f61069f366004613876565b61163c565b3480156106b057600080fd5b506103c56106bf366004613f38565b611718565b3480156106d057600080fd5b506102eb6106df3660046139ae565b6117e7565b3480156106f057600080fd5b506103c56106ff366004613f55565b600160209081526000928352604080842090915290825290205481565b34801561072857600080fd5b50600254610338906001600160a01b031681565b34801561074857600080fd5b5061029f610757366004613f88565b611800565b34801561076857600080fd5b506102eb6119b1565b34801561077d57600080fd5b5061029f61078c3660046139c9565b6119c0565b34801561079d57600080fd5b5061029f6107ac366004613fbc565b611a19565b3480156107bd57600080fd5b5061029f6107cc366004613fd8565b611a67565b3480156107dd57600080fd5b506103c5611b2b565b3480156107f257600080fd5b506102eb611b3b565b34801561080757600080fd5b5061029f610816366004613d47565b611b48565b34801561082757600080fd5b5061029f6108363660046139ae565b611be9565b34801561084757600080fd5b50610850600181565b60405161ffff90911681526020016102cd565b34801561086f57600080fd5b506103387f000000000000000000000000000000000000000000000000000000000000000081565b3480156108a357600080fd5b5061029f6108b2366004614004565b611c31565b61029f6108c536600461406f565b611c63565b3480156108d657600080fd5b506103c561271081565b3480156108ec57600080fd5b506004546108509061ffff1681565b34801561090757600080fd5b506102eb6109163660046139c9565b611c7f565b34801561092757600080fd5b5061029f610936366004614183565b611cbc565b34801561094757600080fd5b5061029f610956366004613f38565b611d68565b34801561096757600080fd5b5061029f610976366004613fbc565b611daf565b61029f610989366004613876565b611dfd565b34801561099a57600080fd5b5061029f6109a93660046141f1565b612013565b3480156109ba57600080fd5b506102eb6120ac565b3480156109cf57600080fd5b506102c16109de36600461422d565b6120dd565b3480156109ef57600080fd5b5061029f6109fe366004613f38565b61210b565b348015610a0f57600080fd5b506102eb610a1e366004614266565b612157565b348015610a2f57600080fd5b506103c5610a3e3660046139ae565b60076020526000908152604090205481565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610acd5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526020819052604081208054610aeb906142b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b17906142b3565b8015610b645780601f10610b3957610100808354040283529160200191610b64565b820191906000526020600020905b815481529060010190602001808311610b4757829003601f168201915b50505050509050805186869050148015610b7f575060008151115b8015610ba7575080516020820120604051610b9d90889088906142e8565b6040518091039020145b610c025760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610ac4565b610c788787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a93509150889088908190840183828082843760009201919091525061221792505050565b50505050505050565b6000610c8c82612290565b92915050565b6060600a8054610ca1906142b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610ccd906142b3565b8015610d1a5780601f10610cef57610100808354040283529160200191610d1a565b820191906000526020600020905b815481529060010190602001808311610cfd57829003601f168201915b5050505050905090565b6002546001600160a01b03163314610d4e5760405162461bcd60e51b8152600401610ac4906142f8565b6040516307e0db1760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610db457600080fd5b505af1158015610dc8573d6000803e3d6000fd5b5050505050565b6000610dda826122b5565b610e3e5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a20617070726f76656420717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610ac4565b506000908152600e60205260409020546001600160a01b031690565b6000610e6582611628565b9050806001600160a01b0316836001600160a01b03161415610ed55760405162461bcd60e51b8152602060048201526024808201527f4552433732315073693a20617070726f76616c20746f2063757272656e74206f6044820152633bb732b960e11b6064820152608401610ac4565b336001600160a01b0382161480610ef15750610ef181336120dd565b610f615760405162461bcd60e51b815260206004820152603b60248201527f4552433732315073693a20617070726f76652063616c6c6572206973206e6f7460448201527a081bdddb995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b602a1b6064820152608401610ac4565b610f6b83836122d1565b505050565b6002546001600160a01b03163314610f9a5760405162461bcd60e51b8152600401610ac4906142f8565b60008111610fa757600080fd5b600555565b6002546001600160a01b03163314610fd65760405162461bcd60e51b8152600401610ac4906142f8565b6040516310ddb13760e01b815261ffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906310ddb13790602401610d9a565b6000611030611b2b565b905090565b61103f338261233f565b61105b5760405162461bcd60e51b8152600401610ac49061432f565b610f6b83838361240c565b60008061108e8787611077886125e4565b87876040518060200160405280600081525061117f565b915091509550959350505050565b604080518082019091526012546001600160a01b038116808352600160a01b90910462ffffff16602083018190529091600091612710906110dd9086614399565b6110e791906143ce565b9150509250929050565b601180546110fe906142b3565b80601f016020809104026020016040519081016040528092919081815260200182805461112a906142b3565b80156111775780601f1061114c57610100808354040283529160200191611177565b820191906000526020600020905b81548152906001019060200180831161115a57829003601f168201915b505050505081565b60008060008788888660405160200161119b949392919061441d565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340a7bb10906111ff908c90309086908c908c90600401614475565b604080518083038186803b15801561121657600080fd5b505afa15801561122a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124e91906144c9565b60045491945092506000906127109061126b9061ffff1686614399565b61127591906143ce565b905061128181856144ed565b93505050965096945050505050565b61ffff8316600090815260208190526040812080548291906112b1906142b3565b80601f01602080910402602001604051908101604052809291908181526020018280546112dd906142b3565b801561132a5780601f106112ff5761010080835404028352916020019161132a565b820191906000526020600020905b81548152906001019060200180831161130d57829003601f168201915b5050505050905083836040516113419291906142e8565b60405180910390208180519060200120149150509392505050565b610f6b83838360405180602001604052806000815250611c31565b6002546001600160a01b031633146113a15760405162461bcd60e51b8152600401610ac4906142f8565b6040516342d65a8d60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906342d65a8d906113f19086908690869060040161452e565b600060405180830381600087803b15801561140b57600080fd5b505af1158015610c78573d6000803e3d6000fd5b6002546001600160a01b031633146114495760405162461bcd60e51b8152600401610ac4906142f8565b600082116114a55760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610ac4565b61ffff85166000908152600760205260409020829055806115135760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610ac4565b61ffff8516600090815260066020908152604091829020839055905161153f918691869130910161454c565b60408051601f1981840301815291815261ffff871660009081526020818152919020825161157293919290910190613767565b50600080516020614add8339815191528585856040516115949392919061452e565b60405180910390a15050505050565b610c788787876115b2886125e4565b878787604051806020016040528060008152506040518060200160405280600081525061262f565b6002546001600160a01b031633146116045760405162461bcd60e51b8152600401610ac4906142f8565b6012805462ffffff909216600160a01b0262ffffff60a01b19909216919091179055565b6000806116348361280b565b509392505050565b33301461169a5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610ac4565b6117108686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152899350915087908790819084018382808284376000920191909152506128a292505050565b505050505050565b60006001600160a01b0382166117865760405162461bcd60e51b815260206004820152602d60248201527f4552433732315073693a2062616c616e636520717565727920666f722074686560448201526c207a65726f206164647265737360981b6064820152608401610ac4565b6000805b600d548110156117e05761179d816122b5565b156117d0576117ab81611628565b6001600160a01b0316846001600160a01b031614156117d0576117cd8261456d565b91505b6117d98161456d565b905061178a565b5092915050565b600060208190529081526040902080546110fe906142b3565b80516020808301919091206000818152600890925260409091206002015460ff1661182a57600080fd5b60008280602001905181019061184091906145cd565b506000858152600860205260408120805460019091015492955090935061187f925061ffff811691620100009091046001600160a01b03169085612af2565b600084815260086020526040902060010154909150811161189f57600080fd5b81518114156119175760008381526008602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba2339061190a9085815260200190565b60405180910390a16119ab565b60408051608081018252600085815260086020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b50505050565b6060600b8054610ca1906142b3565b6002546001600160a01b031633146119ea5760405162461bcd60e51b8152600401610ac4906142f8565b6127106119f5611026565b1115611a0057600080fd5b600254611a16906001600160a01b031682612b44565b50565b6002546001600160a01b03163314611a435760405162461bcd60e51b8152600401610ac4906142f8565b60008111611a5057600080fd5b61ffff909116600090815260066020526040902055565b6001600160a01b038216331415611abf5760405162461bcd60e51b815260206004820152601c60248201527b22a9219b9918a839b49d1030b8383937bb32903a379031b0b63632b960211b6044820152606401610ac4565b336000818152600f602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600080600d5461103091906146c1565b601080546110fe906142b3565b6002546001600160a01b03163314611b725760405162461bcd60e51b8152600401610ac4906142f8565b818130604051602001611b879392919061454c565b60408051601f1981840301815291815261ffff8516600090815260208181529190208251611bba93919290910190613767565b50600080516020614add833981519152838383604051611bdc9392919061452e565b60405180910390a1505050565b6004546201000090046001600160a01b03163314611c0657600080fd5b6127108161ffff161115611c1957600080fd5b6004805461ffff191661ffff92909216919091179055565b611c3b338361233f565b611c575760405162461bcd60e51b8152600401610ac49061432f565b6119ab84848484612b62565b611c7489898989898989898961262f565b505050505050505050565b6060611c89612b97565b6011611c9484612bb8565b604051602001611ca693929190614772565b6040516020818303038152906040529050919050565b6002546001600160a01b03163314611ce65760405162461bcd60e51b8152600401610ac4906142f8565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cbed8b9c90611d3a90889088908890889088906004016147cb565b600060405180830381600087803b158015611d5457600080fd5b505af1158015611c74573d6000803e3d6000fd5b6004546201000090046001600160a01b03163314611d8557600080fd5b600480546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6002546001600160a01b03163314611dd95760405162461bcd60e51b8152600401610ac4906142f8565b60008111611de657600080fd5b61ffff909116600090815260076020526040902055565b61ffff86166000908152600360205260408082209051611e2090889088906142e8565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611ea05760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610ac4565b808383604051611eb19291906142e8565b604051809103902014611f105760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610ac4565b61ffff87166000908152600360205260408082209051611f3390899089906142e8565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252611fcb918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506128a292505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e587878787856040516120029594939291906147f9565b60405180910390a150505050505050565b6002546001600160a01b0316331461203d5760405162461bcd60e51b8152600401610ac4906142f8565b6000811161204a57600080fd5b61ffff83811660008181526001602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611bdc565b60606120b6612b97565b60106040516020016120c9929190614834565b604051602081830303815290604052905090565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205460ff1690565b6002546001600160a01b031633146121355760405162461bcd60e51b8152600401610ac4906142f8565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f5ecbdbc9060840160006040518083038186803b1580156121d257600080fd5b505afa1580156121e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261220e9190810190614852565b95945050505050565b60008061227a5a60966366ad5c8a60e01b8989898960405160240161223f9493929190614886565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190612cb5565b9150915081611710576117108686868685612d3f565b60006001600160e01b031982166380ac58cd60e01b1480610c8c5750610c8c82612dcd565b60006122c0600d5490565b82108015610c8c5750600192915050565b6000818152600e6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061230682611628565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061234a826122b5565b6123ae5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a206f70657261746f7220717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610ac4565b60006123b983611628565b9050806001600160a01b0316846001600160a01b031614806123f45750836001600160a01b03166123e984610dcf565b6001600160a01b0316145b80612404575061240481856120dd565b949350505050565b6000806124188361280b565b91509150846001600160a01b0316826001600160a01b0316146124925760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a207472616e73666572206f6620746f6b656e2074686160448201526b3a1034b9903737ba1037bbb760a11b6064820152608401610ac4565b6001600160a01b0384166124f85760405162461bcd60e51b815260206004820152602760248201527f4552433732315073693a207472616e7366657220746f20746865207a65726f206044820152666164647265737360c81b6064820152608401610ac4565b6125036000846122d1565b60006125108460016144ed565b600881901c600090815260096020526040902054909150600160ff1b60ff83161c161580156125405750600d5481105b15612577576000818152600c6020526040902080546001600160a01b0319166001600160a01b038816179055612577600982612e02565b6000848152600c6020526040902080546001600160a01b0319166001600160a01b0387161790558184146125b0576125b0600985612e02565b83856001600160a01b0316876001600160a01b0316600080516020614afd83398151915260405160405180910390a4611710565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061261e5761261e6148c4565b602090810291909101015292915050565b60008651116126765760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610ac4565b61ffff8816600090815260066020526040902054865111156126e55760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b6064820152608401610ac4565b60005b8651811015612728576127168a8a8a8a8581518110612709576127096148c4565b6020026020010151612e2e565b806127208161456d565b9150506126e8565b50600087838884604051602001612742949392919061441d565b6040516020818303038152906040529050612787896001868a51600760008f61ffff1661ffff168152602001908152602001600020546127829190614399565b612f02565b600061279234612fdc565b90506127a28a83898989866130ae565b886040516127b091906148da565b60405180910390208b6001600160a01b03168b61ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a8b6040516127f691906148f6565b60405180910390a45050505050505050505050565b600080612817836122b5565b6128785760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a206f776e657220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ac4565b61288183613249565b6000818152600c60205260409020546001600160a01b031694909350915050565b600080600080848060200190518101906128bc91906145cd565b6014840151602884015194985092965090945092509060006128e08b848388612af2565b905084518110156129f35760008880519060200120905060405180608001604052808d61ffff168152602001856001600160a01b03168152602001838152602001600115158152506008600083815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816001015560608201518160020160006101000a81548160ff0219169083151502179055509050507f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad7818a6040516129e9929190614909565b60405180910390a1505b826001600160a01b03168a604051612a0b91906148da565b60405180910390208c61ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d99026588604051612a4791906148f6565b60405180910390a4845181148015612a6757506001600160a01b03821615155b15612ae55760405163bace587f60e01b81528b908b9085908590899089906001600160a01b0384169063bace587f90612aac9089908990899088908890600401614922565b600060405180830381600087803b158015612ac657600080fd5b505af1158015612ada573d6000803e3d6000fd5b505050505050505050505b5050505050505050505050565b6000825b825181101561220e576005545a1015612b0e5761220e565b612b328686858481518110612b2557612b256148c4565b6020026020010151613256565b80612b3c8161456d565b915050612af6565b612b5e8282604051806020016040528060008152506132b6565b5050565b612b6d84848461240c565b612b7b8484846001856132d7565b6119ab5760405162461bcd60e51b8152600401610ac490614974565b604080518082019091526007815266697066733a2f2f60c81b602082015290565b606081612bdc5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612c065780612bf08161456d565b9150612bff9050600a836143ce565b9150612be0565b6000816001600160401b03811115612c2057612c20613a6f565b6040519080825280601f01601f191660200182016040528015612c4a576020820181803683370190505b5090505b841561240457612c5f6001836146c1565b9150612c6c600a866149c9565b612c779060306144ed565b60f81b818381518110612c8c57612c8c6148c4565b60200101906001600160f81b031916908160001a905350612cae600a866143ce565b9450612c4e565b6000606060008060008661ffff166001600160401b03811115612cda57612cda613a6f565b6040519080825280601f01601f191660200182016040528015612d04576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115612d26578692505b828152826000602083013e909890975095505050505050565b8180519060200120600360008761ffff1661ffff16815260200190815260200160002085604051612d7091906148da565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c9061159490879087908790879087906149dd565b60006001600160e01b031982166381af209b60e01b1480610c8c57506301ffc9a760e01b6001600160e01b0319831614610c8c565b600881901c600090815260209290925260409091208054600160ff1b60ff9093169290921c9091179055565b612e38338261233f565b612e925760405162461bcd60e51b815260206004820152602560248201527f73656e642063616c6c6572206973206e6f74206f776e6572206e6f72206170706044820152641c9bdd995960da1b6064820152608401610ac4565b836001600160a01b0316612ea582611628565b6001600160a01b031614612ef75760405162461bcd60e51b815260206004820152601960248201527839b2b73210333937b69034b731b7b93932b1ba1037bbb732b960391b6044820152606401610ac4565b6119ab84308361240c565b6000612f0d83613419565b61ffff808716600090815260016020908152604080832093891683529290529081205491925090612f3f9084906144ed565b905060008111612f8e5760405162461bcd60e51b815260206004820152601a602482015279131e905c1c0e881b5a5b91d85cd31a5b5a5d081b9bdd081cd95d60321b6044820152606401610ac4565b808210156117105760405162461bcd60e51b815260206004820152601b60248201527a4c7a4170703a20676173206c696d697420697320746f6f206c6f7760281b6044820152606401610ac4565b600454600090819061271090612ff69061ffff1685614399565b61300091906143ce565b905061300c81846146c1565b915080156130a8576004546040516000916201000090046001600160a01b03169083908381818185875af1925050503d8060008114613067576040519150601f19603f3d011682016040523d82523d6000602084013e61306c565b606091505b50509050806130a65760405162461bcd60e51b8152600401610ac4906020808252600490820152632166656560e01b604082015260600190565b505b50919050565b61ffff8616600090815260208190526040812080546130cc906142b3565b80601f01602080910402602001604051908101604052809291908181526020018280546130f8906142b3565b80156131455780601f1061311a57610100808354040283529160200191613145565b820191906000526020600020905b81548152906001019060200180831161312857829003601f168201915b505050505090508051600014156131b75760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610ac4565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c580310090849061320e908b9086908c908c908c908c90600401614a1b565b6000604051808303818588803b15801561322757600080fd5b505af115801561323b573d6000803e3d6000fd5b505050505050505050505050565b6000610c8c600983613474565b61325f816122b5565b158061328b575061326f816122b5565b801561328b57503061328082611628565b6001600160a01b0316145b61329457600080fd5b61329d816122b5565b6132ab57610f6b8282612b44565b610f6b30838361240c565b60006132c1600d5490565b90506132cd848461356c565b612b7b6000858386865b60006001600160a01b0385163b1561340d57506001835b6132f884866144ed565b81101561340757604051630a85bd0160e11b81526001600160a01b0387169063150b7a02906133319033908b9086908990600401614a82565b602060405180830381600087803b15801561334b57600080fd5b505af192505050801561337b575060408051601f3d908101601f1916820190925261337891810190614abf565b60015b6133d5573d8080156133a9576040519150601f19603f3d011682016040523d82523d6000602084013e6133ae565b606091505b5080516133cd5760405162461bcd60e51b8152600401610ac490614974565b805181602001fd5b8280156133f257506001600160e01b03198116630a85bd0160e11b145b925050806133ff8161456d565b9150506132ee565b5061220e565b50600195945050505050565b600060228251101561346c5760405162461bcd60e51b815260206004820152601c60248201527b4c7a4170703a20696e76616c69642061646170746572506172616d7360201b6044820152606401610ac4565b506022015190565b600881901c60008181526020849052604081205490919060ff808516919082181c80156134b6576134a4816136e5565b60ff168203600884901b179350613563565b600083116135235760405162461bcd60e51b815260206004820152603460248201527f4269744d6170733a205468652073657420626974206265666f7265207468652060448201527334b73232bc103237b2b9b713ba1032bc34b9ba1760611b6064820152608401610ac4565b50600019909101600081815260208690526040902054909190801561355e5761354b816136e5565b60ff0360ff16600884901b179350613563565b6134b6565b50505092915050565b6000613577600d5490565b9050600082116135d75760405162461bcd60e51b815260206004820152602560248201527f4552433732315073693a207175616e74697479206d7573742062652067726561604482015264074657220360dc1b6064820152608401610ac4565b6001600160a01b0383166136395760405162461bcd60e51b815260206004820152602360248201527f4552433732315073693a206d696e7420746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610ac4565b81600d600082825461364b91906144ed565b90915550506000818152600c6020526040902080546001600160a01b0319166001600160a01b038516179055613682600982612e02565b60008061368f84846144ed565b90506001600160a01b038516915082826000600080516020614afd833981519152600080a4600183015b8181146136df5780836000600080516020614afd833981519152600080a46001016136b9565b50610dc8565b60006040518061012001604052806101008152602001614b1d610100913960f87e818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff61372e8561374f565b02901c81518110613741576137416148c4565b016020015160f81c92915050565b600080821161375d57600080fd5b5060008190031690565b828054613773906142b3565b90600052602060002090601f01602090048101928261379557600085556137db565b82601f106137ae57805160ff19168380011785556137db565b828001600101855582156137db579182015b828111156137db5782518255916020019190600101906137c0565b506137e79291506137eb565b5090565b5b808211156137e757600081556001016137ec565b803561ffff8116811461381257600080fd5b919050565b60008083601f84011261382957600080fd5b5081356001600160401b0381111561384057600080fd5b60208301915083602082850101111561385857600080fd5b9250929050565b80356001600160401b038116811461381257600080fd5b6000806000806000806080878903121561388f57600080fd5b61389887613800565b955060208701356001600160401b03808211156138b457600080fd5b6138c08a838b01613817565b90975095508591506138d460408a0161385f565b945060608901359150808211156138ea57600080fd5b506138f789828a01613817565b979a9699509497509295939492505050565b6001600160e01b031981168114611a1657600080fd5b60006020828403121561393157600080fd5b813561393c81613909565b9392505050565b60005b8381101561395e578181015183820152602001613946565b838111156119ab5750506000910152565b60008151808452613987816020860160208601613943565b601f01601f19169290920160200192915050565b60208152600061393c602083018461396f565b6000602082840312156139c057600080fd5b61393c82613800565b6000602082840312156139db57600080fd5b5035919050565b6001600160a01b0381168114611a1657600080fd5b8035613812816139e2565b60008060408385031215613a1557600080fd5b8235613a20816139e2565b946020939093013593505050565b600080600060608486031215613a4357600080fd5b8335613a4e816139e2565b92506020840135613a5e816139e2565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613aad57613aad613a6f565b604052919050565b60006001600160401b03821115613ace57613ace613a6f565b50601f01601f191660200190565b600082601f830112613aed57600080fd5b8135613b00613afb82613ab5565b613a85565b818152846020838601011115613b1557600080fd5b816020850160208301376000918101602001919091529392505050565b8035801515811461381257600080fd5b600080600080600060a08688031215613b5a57600080fd5b613b6386613800565b945060208601356001600160401b0380821115613b7f57600080fd5b613b8b89838a01613adc565b955060408801359450613ba060608901613b32565b93506080880135915080821115613bb657600080fd5b50613bc388828901613adc565b9150509295509295909350565b60008060408385031215613be357600080fd5b50508035926020909101359150565b60006001600160401b03821115613c0b57613c0b613a6f565b5060051b60200190565b600082601f830112613c2657600080fd5b81356020613c36613afb83613bf2565b82815260059290921b84018101918181019086841115613c5557600080fd5b8286015b84811015613c705780358352918301918301613c59565b509695505050505050565b60008060008060008060c08789031215613c9457600080fd5b613c9d87613800565b955060208701356001600160401b0380821115613cb957600080fd5b613cc58a838b01613adc565b96506040890135915080821115613cdb57600080fd5b613ce78a838b01613c15565b9550613cf560608a01613b32565b94506080890135915080821115613d0b57600080fd5b613d178a838b01613adc565b935060a0890135915080821115613d2d57600080fd5b50613d3a89828a01613adc565b9150509295509295509295565b600080600060408486031215613d5c57600080fd5b613d6584613800565b925060208401356001600160401b03811115613d8057600080fd5b613d8c86828701613817565b9497909650939450505050565b600080600080600060808688031215613db157600080fd5b613dba86613800565b945060208601356001600160401b03811115613dd557600080fd5b613de188828901613817565b9699909850959660408101359660609091013595509350505050565b600080600080600080600060e0888a031215613e1857600080fd5b8735613e23816139e2565b9650613e3160208901613800565b955060408801356001600160401b0380821115613e4d57600080fd5b613e598b838c01613adc565b965060608a0135955060808a01359150613e72826139e2565b90935060a089013590613e84826139e2565b90925060c08901359080821115613e9a57600080fd5b50613ea78a828b01613adc565b91505092959891949750929550565b600060208284031215613ec857600080fd5b813562ffffff8116811461393c57600080fd5b600080600060608486031215613ef057600080fd5b613ef984613800565b925060208401356001600160401b03811115613f1457600080fd5b613f2086828701613adc565b925050613f2f6040850161385f565b90509250925092565b600060208284031215613f4a57600080fd5b813561393c816139e2565b60008060408385031215613f6857600080fd5b613f7183613800565b9150613f7f60208401613800565b90509250929050565b600060208284031215613f9a57600080fd5b81356001600160401b03811115613fb057600080fd5b61240484828501613adc565b60008060408385031215613fcf57600080fd5b613a2083613800565b60008060408385031215613feb57600080fd5b8235613ff6816139e2565b9150613f7f60208401613b32565b6000806000806080858703121561401a57600080fd5b8435614025816139e2565b93506020850135614035816139e2565b92506040850135915060608501356001600160401b0381111561405757600080fd5b61406387828801613adc565b91505092959194509250565b60008060008060008060008060006101208a8c03121561408e57600080fd5b6140978a6139f7565b98506140a560208b01613800565b975060408a01356001600160401b03808211156140c157600080fd5b6140cd8d838e01613adc565b985060608c01359150808211156140e357600080fd5b6140ef8d838e01613c15565b97506140fd60808d016139f7565b965061410b60a08d016139f7565b955060c08c013591508082111561412157600080fd5b61412d8d838e01613adc565b945060e08c013591508082111561414357600080fd5b61414f8d838e01613adc565b93506101008c013591508082111561416657600080fd5b506141738c828d01613adc565b9150509295985092959850929598565b60008060008060006080868803121561419b57600080fd5b6141a486613800565b94506141b260208701613800565b93506040860135925060608601356001600160401b038111156141d457600080fd5b6141e088828901613817565b969995985093965092949392505050565b60008060006060848603121561420657600080fd5b61420f84613800565b925061421d60208501613800565b9150604084013590509250925092565b6000806040838503121561424057600080fd5b823561424b816139e2565b9150602083013561425b816139e2565b809150509250929050565b6000806000806080858703121561427c57600080fd5b61428585613800565b935061429360208601613800565b925060408501356142a3816139e2565b9396929550929360600135925050565b600181811c908216806142c757607f821691505b602082108114156130a857634e487b7160e01b600052602260045260246000fd5b8183823760009101908152919050565b6020808252601e908201527f4c7a4170703a2063616c6c6572206973206e6f7420746865206f776e65720000604082015260600190565b60208082526034908201527f4552433732315073693a207472616e736665722063616c6c6572206973206e6f6040820152731d081bdddb995c881b9bdc88185c1c1c9bdd995960621b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156143b3576143b3614383565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826143dd576143dd6143b8565b500490565b600081518084526020808501945080840160005b83811015614412578151875295820195908201906001016143f6565b509495945050505050565b608081526000614430608083018761396f565b8281036020840152614442818761396f565b9050828103604084015261445681866143e2565b9050828103606084015261446a818561396f565b979650505050505050565b61ffff861681526001600160a01b038516602082015260a0604082018190526000906144a39083018661396f565b841515606084015282810360808401526144bd818561396f565b98975050505050505050565b600080604083850312156144dc57600080fd5b505080516020909101519092909150565b6000821982111561450057614500614383565b500190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff8416815260406020820152600061220e604083018486614505565b8284823760609190911b6001600160601b0319169101908152601401919050565b600060001982141561458157614581614383565b5060010190565b600082601f83011261459957600080fd5b81516145a7613afb82613ab5565b8181528460208386010111156145bc57600080fd5b612404826020830160208701613943565b600080600080608085870312156145e357600080fd5b84516001600160401b03808211156145fa57600080fd5b61460688838901614588565b955060209150818701518181111561461d57600080fd5b61462989828a01614588565b95505060408701518181111561463e57600080fd5b8701601f8101891361464f57600080fd5b805161465d613afb82613bf2565b81815260059190911b8201840190848101908b83111561467c57600080fd5b928501925b8284101561469a57835182529285019290850190614681565b60608b01519097509450505050808211156146b457600080fd5b5061406387828801614588565b6000828210156146d3576146d3614383565b500390565b8054600090600181811c90808316806146f257607f831692505b602080841082141561471457634e487b7160e01b600052602260045260246000fd5b818015614728576001811461473957614766565b60ff19861689528489019650614766565b60008881526020902060005b8681101561475e5781548b820152908501908301614745565b505084890196505b50505050505092915050565b60008451614784818460208901613943565b614790818401866146d8565b9050602f60f81b815283516147ac816001840160208801613943565b64173539b7b760d91b6001929091019182015260060195945050505050565b600061ffff80881683528087166020840152508460408301526080606083015261446a608083018486614505565b61ffff86168152608060208201526000614817608083018688614505565b6001600160401b0394909416604083015250606001529392505050565b60008351614846818460208801613943565b61220e818401856146d8565b60006020828403121561486457600080fd5b81516001600160401b0381111561487a57600080fd5b61240484828501614588565b61ffff851681526080602082015260006148a3608083018661396f565b6001600160401b0385166040840152828103606084015261446a818561396f565b634e487b7160e01b600052603260045260246000fd5b600082516148ec818460208701613943565b9190910192915050565b60208152600061393c60208301846143e2565b828152604060208201526000612404604083018461396f565b61ffff8616815260a06020820152600061493f60a083018761396f565b6001600160a01b0386166040840152828103606084015261496081866143e2565b905082810360808401526144bd818561396f565b60208082526035908201527f4552433732315073693a207472616e7366657220746f206e6f6e20455243373260408201527418a932b1b2b4bb32b91034b6b83632b6b2b73a32b960591b606082015260800190565b6000826149d8576149d86143b8565b500690565b61ffff8616815260a0602082015260006149fa60a083018761396f565b6001600160401b03861660408401528281036060840152614960818661396f565b61ffff8716815260c060208201526000614a3860c083018861396f565b8281036040840152614a4a818861396f565b6001600160a01b0387811660608601528616608085015283810360a08501529050614a75818561396f565b9998505050505050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614ab59083018461396f565b9695505050505050565b600060208284031215614ad157600080fd5b815161393c8161390956fe8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ceddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8a26469706673582212205419fe7d71e8c77355e02a9e369bccd3b08210e7c851dd210beebbe96d0cd76364736f6c6343000809003300000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000f285e70ca2002b796a575e473285282bbf39d790000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000003c2269811836af69497e5f486a85d7316753cf6200000000000000000000000000000000000000000000000000000000000000105a6b616c69656e204578706c6f7265720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a4b580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b6261666b726569677a346773623472326263756e736468377532736233717233686667646f6868796d73697774703271636177746b616d367264610000000000000000000000000000000000000000000000000000000000000000000000003b6261667962656966746d756f786e686c6d6d6f62666872616c6c69616233707471757764787033646a6979343261357067643236326f6d6a3335710000000000
Deployed Bytecode
0x60806040526004361061027a5760003560e01c80621d35671461027f57806301ffc9a7146102a157806306fdde03146102d657806307e0db17146102f8578063081812fc14610318578063095ea7b3146103505780630b4cad4c1461037057806310ddb1371461039057806318160ddd146103b057806322a3ecf9146103d357806323b872dd146104565780632a205e3d146104765780632a55205a146104ab5780632dd0066e146104ea5780633b5aeddb146104ff5780633d8b38f61461051f57806342842e0e1461053f57806342d65a8d1461055f57806346a438161461057f578063482881901461059f5780634ac3f4ff146105b557806351905636146105e257806352a284a2146105f55780635b8c41e6146106155780636352211e1461066457806366ad5c8a1461068457806370a08231146106a45780637533d788146106c45780638cfd8f5c146106e45780638da5cb5b1461071c5780638ffa1f2a1461073c57806395d89b411461075c5780639d5aef30146107715780639ea5d6b114610791578063a22cb465146107b1578063a2309ff8146107d1578063a5097ebf146107e6578063a6c3d165146107fb578063a7e0d43d1461081b578063af3fb21c1461083b578063b353aaa714610863578063b88d4fde14610897578063c145c54b146108b7578063c4461834146108ca578063c4ed6f58146108e0578063c87b56dd146108fb578063cbed8b9c1461091b578063d0ebdbe71461093b578063d12473a51461095b578063d1deba1f1461097b578063df2a5b3b1461098e578063e8a3d485146109ae578063e985e9c5146109c3578063f2fde38b146109e3578063f5ecbdbc14610a03578063fa25f9b614610a23575b600080fd5b34801561028b57600080fd5b5061029f61029a366004613876565b610a50565b005b3480156102ad57600080fd5b506102c16102bc36600461391f565b610c81565b60405190151581526020015b60405180910390f35b3480156102e257600080fd5b506102eb610c92565b6040516102cd919061399b565b34801561030457600080fd5b5061029f6103133660046139ae565b610d24565b34801561032457600080fd5b506103386103333660046139c9565b610dcf565b6040516001600160a01b0390911681526020016102cd565b34801561035c57600080fd5b5061029f61036b366004613a02565b610e5a565b34801561037c57600080fd5b5061029f61038b3660046139c9565b610f70565b34801561039c57600080fd5b5061029f6103ab3660046139ae565b610fac565b3480156103bc57600080fd5b506103c5611026565b6040519081526020016102cd565b3480156103df57600080fd5b506104276103ee3660046139c9565b60086020526000908152604090208054600182015460029092015461ffff821692620100009092046001600160a01b0316919060ff1684565b6040805161ffff90951685526001600160a01b03909316602085015291830152151560608201526080016102cd565b34801561046257600080fd5b5061029f610471366004613a2e565b611035565b34801561048257600080fd5b50610496610491366004613b42565b611066565b604080519283526020830191909152016102cd565b3480156104b757600080fd5b506104cb6104c6366004613bd0565b61109c565b604080516001600160a01b0390931683526020830191909152016102cd565b3480156104f657600080fd5b506102eb6110f1565b34801561050b57600080fd5b5061049661051a366004613c7b565b61117f565b34801561052b57600080fd5b506102c161053a366004613d47565b611290565b34801561054b57600080fd5b5061029f61055a366004613a2e565b61135c565b34801561056b57600080fd5b5061029f61057a366004613d47565b611377565b34801561058b57600080fd5b5061029f61059a366004613d99565b61141f565b3480156105ab57600080fd5b506103c560055481565b3480156105c157600080fd5b506103c56105d03660046139ae565b60066020526000908152604090205481565b61029f6105f0366004613dfd565b6115a3565b34801561060157600080fd5b5061029f610610366004613eb6565b6115da565b34801561062157600080fd5b506103c5610630366004613edb565b6003602090815260009384526040808520845180860184018051928152908401958401959095209452929052825290205481565b34801561067057600080fd5b5061033861067f3660046139c9565b611628565b34801561069057600080fd5b5061029f61069f366004613876565b61163c565b3480156106b057600080fd5b506103c56106bf366004613f38565b611718565b3480156106d057600080fd5b506102eb6106df3660046139ae565b6117e7565b3480156106f057600080fd5b506103c56106ff366004613f55565b600160209081526000928352604080842090915290825290205481565b34801561072857600080fd5b50600254610338906001600160a01b031681565b34801561074857600080fd5b5061029f610757366004613f88565b611800565b34801561076857600080fd5b506102eb6119b1565b34801561077d57600080fd5b5061029f61078c3660046139c9565b6119c0565b34801561079d57600080fd5b5061029f6107ac366004613fbc565b611a19565b3480156107bd57600080fd5b5061029f6107cc366004613fd8565b611a67565b3480156107dd57600080fd5b506103c5611b2b565b3480156107f257600080fd5b506102eb611b3b565b34801561080757600080fd5b5061029f610816366004613d47565b611b48565b34801561082757600080fd5b5061029f6108363660046139ae565b611be9565b34801561084757600080fd5b50610850600181565b60405161ffff90911681526020016102cd565b34801561086f57600080fd5b506103387f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6281565b3480156108a357600080fd5b5061029f6108b2366004614004565b611c31565b61029f6108c536600461406f565b611c63565b3480156108d657600080fd5b506103c561271081565b3480156108ec57600080fd5b506004546108509061ffff1681565b34801561090757600080fd5b506102eb6109163660046139c9565b611c7f565b34801561092757600080fd5b5061029f610936366004614183565b611cbc565b34801561094757600080fd5b5061029f610956366004613f38565b611d68565b34801561096757600080fd5b5061029f610976366004613fbc565b611daf565b61029f610989366004613876565b611dfd565b34801561099a57600080fd5b5061029f6109a93660046141f1565b612013565b3480156109ba57600080fd5b506102eb6120ac565b3480156109cf57600080fd5b506102c16109de36600461422d565b6120dd565b3480156109ef57600080fd5b5061029f6109fe366004613f38565b61210b565b348015610a0f57600080fd5b506102eb610a1e366004614266565b612157565b348015610a2f57600080fd5b506103c5610a3e3660046139ae565b60076020526000908152604090205481565b336001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf621614610acd5760405162461bcd60e51b815260206004820152601e60248201527f4c7a4170703a20696e76616c696420656e64706f696e742063616c6c6572000060448201526064015b60405180910390fd5b61ffff861660009081526020819052604081208054610aeb906142b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b17906142b3565b8015610b645780601f10610b3957610100808354040283529160200191610b64565b820191906000526020600020905b815481529060010190602001808311610b4757829003601f168201915b50505050509050805186869050148015610b7f575060008151115b8015610ba7575080516020820120604051610b9d90889088906142e8565b6040518091039020145b610c025760405162461bcd60e51b815260206004820152602660248201527f4c7a4170703a20696e76616c696420736f757263652073656e64696e6720636f6044820152651b9d1c9858dd60d21b6064820152608401610ac4565b610c788787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a018190048102820181019092528881528a93509150889088908190840183828082843760009201919091525061221792505050565b50505050505050565b6000610c8c82612290565b92915050565b6060600a8054610ca1906142b3565b80601f0160208091040260200160405190810160405280929190818152602001828054610ccd906142b3565b8015610d1a5780601f10610cef57610100808354040283529160200191610d1a565b820191906000526020600020905b815481529060010190602001808311610cfd57829003601f168201915b5050505050905090565b6002546001600160a01b03163314610d4e5760405162461bcd60e51b8152600401610ac4906142f8565b6040516307e0db1760e01b815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906307e0db17906024015b600060405180830381600087803b158015610db457600080fd5b505af1158015610dc8573d6000803e3d6000fd5b5050505050565b6000610dda826122b5565b610e3e5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a20617070726f76656420717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610ac4565b506000908152600e60205260409020546001600160a01b031690565b6000610e6582611628565b9050806001600160a01b0316836001600160a01b03161415610ed55760405162461bcd60e51b8152602060048201526024808201527f4552433732315073693a20617070726f76616c20746f2063757272656e74206f6044820152633bb732b960e11b6064820152608401610ac4565b336001600160a01b0382161480610ef15750610ef181336120dd565b610f615760405162461bcd60e51b815260206004820152603b60248201527f4552433732315073693a20617070726f76652063616c6c6572206973206e6f7460448201527a081bdddb995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b602a1b6064820152608401610ac4565b610f6b83836122d1565b505050565b6002546001600160a01b03163314610f9a5760405162461bcd60e51b8152600401610ac4906142f8565b60008111610fa757600080fd5b600555565b6002546001600160a01b03163314610fd65760405162461bcd60e51b8152600401610ac4906142f8565b6040516310ddb13760e01b815261ffff821660048201527f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b0316906310ddb13790602401610d9a565b6000611030611b2b565b905090565b61103f338261233f565b61105b5760405162461bcd60e51b8152600401610ac49061432f565b610f6b83838361240c565b60008061108e8787611077886125e4565b87876040518060200160405280600081525061117f565b915091509550959350505050565b604080518082019091526012546001600160a01b038116808352600160a01b90910462ffffff16602083018190529091600091612710906110dd9086614399565b6110e791906143ce565b9150509250929050565b601180546110fe906142b3565b80601f016020809104026020016040519081016040528092919081815260200182805461112a906142b3565b80156111775780601f1061114c57610100808354040283529160200191611177565b820191906000526020600020905b81548152906001019060200180831161115a57829003601f168201915b505050505081565b60008060008788888660405160200161119b949392919061441d565b60408051601f198184030181529082905263040a7bb160e41b825291506001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906340a7bb10906111ff908c90309086908c908c90600401614475565b604080518083038186803b15801561121657600080fd5b505afa15801561122a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124e91906144c9565b60045491945092506000906127109061126b9061ffff1686614399565b61127591906143ce565b905061128181856144ed565b93505050965096945050505050565b61ffff8316600090815260208190526040812080548291906112b1906142b3565b80601f01602080910402602001604051908101604052809291908181526020018280546112dd906142b3565b801561132a5780601f106112ff5761010080835404028352916020019161132a565b820191906000526020600020905b81548152906001019060200180831161130d57829003601f168201915b5050505050905083836040516113419291906142e8565b60405180910390208180519060200120149150509392505050565b610f6b83838360405180602001604052806000815250611c31565b6002546001600160a01b031633146113a15760405162461bcd60e51b8152600401610ac4906142f8565b6040516342d65a8d60e01b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf6216906342d65a8d906113f19086908690869060040161452e565b600060405180830381600087803b15801561140b57600080fd5b505af1158015610c78573d6000803e3d6000fd5b6002546001600160a01b031633146114495760405162461bcd60e51b8152600401610ac4906142f8565b600082116114a55760405162461bcd60e51b815260206004820152602360248201527f647374436861696e4964546f5472616e73666572476173206d7573742062652060448201526203e20360ec1b6064820152608401610ac4565b61ffff85166000908152600760205260409020829055806115135760405162461bcd60e51b815260206004820152602260248201527f647374436861696e4964546f42617463684c696d6974206d757374206265203e604482015261020360f41b6064820152608401610ac4565b61ffff8516600090815260066020908152604091829020839055905161153f918691869130910161454c565b60408051601f1981840301815291815261ffff871660009081526020818152919020825161157293919290910190613767565b50600080516020614add8339815191528585856040516115949392919061452e565b60405180910390a15050505050565b610c788787876115b2886125e4565b878787604051806020016040528060008152506040518060200160405280600081525061262f565b6002546001600160a01b031633146116045760405162461bcd60e51b8152600401610ac4906142f8565b6012805462ffffff909216600160a01b0262ffffff60a01b19909216919091179055565b6000806116348361280b565b509392505050565b33301461169a5760405162461bcd60e51b815260206004820152602660248201527f4e6f6e626c6f636b696e674c7a4170703a2063616c6c6572206d7573742062656044820152650204c7a4170760d41b6064820152608401610ac4565b6117108686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8901819004810282018101909252878152899350915087908790819084018382808284376000920191909152506128a292505050565b505050505050565b60006001600160a01b0382166117865760405162461bcd60e51b815260206004820152602d60248201527f4552433732315073693a2062616c616e636520717565727920666f722074686560448201526c207a65726f206164647265737360981b6064820152608401610ac4565b6000805b600d548110156117e05761179d816122b5565b156117d0576117ab81611628565b6001600160a01b0316846001600160a01b031614156117d0576117cd8261456d565b91505b6117d98161456d565b905061178a565b5092915050565b600060208190529081526040902080546110fe906142b3565b80516020808301919091206000818152600890925260409091206002015460ff1661182a57600080fd5b60008280602001905181019061184091906145cd565b506000858152600860205260408120805460019091015492955090935061187f925061ffff811691620100009091046001600160a01b03169085612af2565b600084815260086020526040902060010154909150811161189f57600080fd5b81518114156119175760008381526008602052604080822080546001600160b01b031916815560018101929092556002909101805460ff19169055517fd7be02b8dd0d27bd0517a9cb4d7469ce27df4313821ae5ec1ff69acc594ba2339061190a9085815260200190565b60405180910390a16119ab565b60408051608081018252600085815260086020818152848320805461ffff80821687526001600160a01b03620100008084048216868a019081529989018b8152600160608b01818152998f90529790965297519851169096026001600160b01b03199091169690951695909517939093178455915191830191909155516002909101805491151560ff199092169190911790555b50505050565b6060600b8054610ca1906142b3565b6002546001600160a01b031633146119ea5760405162461bcd60e51b8152600401610ac4906142f8565b6127106119f5611026565b1115611a0057600080fd5b600254611a16906001600160a01b031682612b44565b50565b6002546001600160a01b03163314611a435760405162461bcd60e51b8152600401610ac4906142f8565b60008111611a5057600080fd5b61ffff909116600090815260066020526040902055565b6001600160a01b038216331415611abf5760405162461bcd60e51b815260206004820152601c60248201527b22a9219b9918a839b49d1030b8383937bb32903a379031b0b63632b960211b6044820152606401610ac4565b336000818152600f602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600080600d5461103091906146c1565b601080546110fe906142b3565b6002546001600160a01b03163314611b725760405162461bcd60e51b8152600401610ac4906142f8565b818130604051602001611b879392919061454c565b60408051601f1981840301815291815261ffff8516600090815260208181529190208251611bba93919290910190613767565b50600080516020614add833981519152838383604051611bdc9392919061452e565b60405180910390a1505050565b6004546201000090046001600160a01b03163314611c0657600080fd5b6127108161ffff161115611c1957600080fd5b6004805461ffff191661ffff92909216919091179055565b611c3b338361233f565b611c575760405162461bcd60e51b8152600401610ac49061432f565b6119ab84848484612b62565b611c7489898989898989898961262f565b505050505050505050565b6060611c89612b97565b6011611c9484612bb8565b604051602001611ca693929190614772565b6040516020818303038152906040529050919050565b6002546001600160a01b03163314611ce65760405162461bcd60e51b8152600401610ac4906142f8565b6040516332fb62e760e21b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063cbed8b9c90611d3a90889088908890889088906004016147cb565b600060405180830381600087803b158015611d5457600080fd5b505af1158015611c74573d6000803e3d6000fd5b6004546201000090046001600160a01b03163314611d8557600080fd5b600480546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6002546001600160a01b03163314611dd95760405162461bcd60e51b8152600401610ac4906142f8565b60008111611de657600080fd5b61ffff909116600090815260076020526040902055565b61ffff86166000908152600360205260408082209051611e2090889088906142e8565b90815260408051602092819003830190206001600160401b03871660009081529252902054905080611ea05760405162461bcd60e51b815260206004820152602360248201527f4e6f6e626c6f636b696e674c7a4170703a206e6f2073746f726564206d65737360448201526261676560e81b6064820152608401610ac4565b808383604051611eb19291906142e8565b604051809103902014611f105760405162461bcd60e51b815260206004820152602160248201527f4e6f6e626c6f636b696e674c7a4170703a20696e76616c6964207061796c6f616044820152601960fa1b6064820152608401610ac4565b61ffff87166000908152600360205260408082209051611f3390899089906142e8565b90815260408051602092819003830181206001600160401b038916600090815290845282902093909355601f88018290048202830182019052868252611fcb918991899089908190840183828082843760009201919091525050604080516020601f8a018190048102820181019092528881528a9350915088908890819084018382808284376000920191909152506128a292505050565b7fc264d91f3adc5588250e1551f547752ca0cfa8f6b530d243b9f9f4cab10ea8e587878787856040516120029594939291906147f9565b60405180910390a150505050505050565b6002546001600160a01b0316331461203d5760405162461bcd60e51b8152600401610ac4906142f8565b6000811161204a57600080fd5b61ffff83811660008181526001602090815260408083209487168084529482529182902085905581519283528201929092529081018290527f9d5c7c0b934da8fefa9c7760c98383778a12dfbfc0c3b3106518f43fb9508ac090606001611bdc565b60606120b6612b97565b60106040516020016120c9929190614834565b604051602081830303815290604052905090565b6001600160a01b039182166000908152600f6020908152604080832093909416825291909152205460ff1690565b6002546001600160a01b031633146121355760405162461bcd60e51b8152600401610ac4906142f8565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b604051633d7b2f6f60e21b815261ffff808616600483015284166024820152306044820152606481018290526060907f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf626001600160a01b03169063f5ecbdbc9060840160006040518083038186803b1580156121d257600080fd5b505afa1580156121e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261220e9190810190614852565b95945050505050565b60008061227a5a60966366ad5c8a60e01b8989898960405160240161223f9493929190614886565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915230929190612cb5565b9150915081611710576117108686868685612d3f565b60006001600160e01b031982166380ac58cd60e01b1480610c8c5750610c8c82612dcd565b60006122c0600d5490565b82108015610c8c5750600192915050565b6000818152600e6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061230682611628565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061234a826122b5565b6123ae5760405162461bcd60e51b815260206004820152602f60248201527f4552433732315073693a206f70657261746f7220717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610ac4565b60006123b983611628565b9050806001600160a01b0316846001600160a01b031614806123f45750836001600160a01b03166123e984610dcf565b6001600160a01b0316145b80612404575061240481856120dd565b949350505050565b6000806124188361280b565b91509150846001600160a01b0316826001600160a01b0316146124925760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a207472616e73666572206f6620746f6b656e2074686160448201526b3a1034b9903737ba1037bbb760a11b6064820152608401610ac4565b6001600160a01b0384166124f85760405162461bcd60e51b815260206004820152602760248201527f4552433732315073693a207472616e7366657220746f20746865207a65726f206044820152666164647265737360c81b6064820152608401610ac4565b6125036000846122d1565b60006125108460016144ed565b600881901c600090815260096020526040902054909150600160ff1b60ff83161c161580156125405750600d5481105b15612577576000818152600c6020526040902080546001600160a01b0319166001600160a01b038816179055612577600982612e02565b6000848152600c6020526040902080546001600160a01b0319166001600160a01b0387161790558184146125b0576125b0600985612e02565b83856001600160a01b0316876001600160a01b0316600080516020614afd83398151915260405160405180910390a4611710565b6040805160018082528183019092526060916000919060208083019080368337019050509050828160008151811061261e5761261e6148c4565b602090810291909101015292915050565b60008651116126765760405162461bcd60e51b8152602060048201526013602482015272746f6b656e4964735b5d20697320656d70747960681b6044820152606401610ac4565b61ffff8816600090815260066020526040902054865111156126e55760405162461bcd60e51b815260206004820152602260248201527f62617463682073697a65206578636565647320647374206261746368206c696d6044820152611a5d60f21b6064820152608401610ac4565b60005b8651811015612728576127168a8a8a8a8581518110612709576127096148c4565b6020026020010151612e2e565b806127208161456d565b9150506126e8565b50600087838884604051602001612742949392919061441d565b6040516020818303038152906040529050612787896001868a51600760008f61ffff1661ffff168152602001908152602001600020546127829190614399565b612f02565b600061279234612fdc565b90506127a28a83898989866130ae565b886040516127b091906148da565b60405180910390208b6001600160a01b03168b61ffff167fe1b87c47fdeb4f9cbadbca9df3af7aba453bb6e501075d0440d88125b711522a8b6040516127f691906148f6565b60405180910390a45050505050505050505050565b600080612817836122b5565b6128785760405162461bcd60e51b815260206004820152602c60248201527f4552433732315073693a206f776e657220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610ac4565b61288183613249565b6000818152600c60205260409020546001600160a01b031694909350915050565b600080600080848060200190518101906128bc91906145cd565b6014840151602884015194985092965090945092509060006128e08b848388612af2565b905084518110156129f35760008880519060200120905060405180608001604052808d61ffff168152602001856001600160a01b03168152602001838152602001600115158152506008600083815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b031602179055506040820151816001015560608201518160020160006101000a81548160ff0219169083151502179055509050507f10e0b70d256bccc84b7027506978bd8b68984a870788b93b479def144c839ad7818a6040516129e9929190614909565b60405180910390a1505b826001600160a01b03168a604051612a0b91906148da565b60405180910390208c61ffff167f5b821db8a46f8ecbe1941ba2f51cfeea9643268b56631f70d45e2a745d99026588604051612a4791906148f6565b60405180910390a4845181148015612a6757506001600160a01b03821615155b15612ae55760405163bace587f60e01b81528b908b9085908590899089906001600160a01b0384169063bace587f90612aac9089908990899088908890600401614922565b600060405180830381600087803b158015612ac657600080fd5b505af1158015612ada573d6000803e3d6000fd5b505050505050505050505b5050505050505050505050565b6000825b825181101561220e576005545a1015612b0e5761220e565b612b328686858481518110612b2557612b256148c4565b6020026020010151613256565b80612b3c8161456d565b915050612af6565b612b5e8282604051806020016040528060008152506132b6565b5050565b612b6d84848461240c565b612b7b8484846001856132d7565b6119ab5760405162461bcd60e51b8152600401610ac490614974565b604080518082019091526007815266697066733a2f2f60c81b602082015290565b606081612bdc5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612c065780612bf08161456d565b9150612bff9050600a836143ce565b9150612be0565b6000816001600160401b03811115612c2057612c20613a6f565b6040519080825280601f01601f191660200182016040528015612c4a576020820181803683370190505b5090505b841561240457612c5f6001836146c1565b9150612c6c600a866149c9565b612c779060306144ed565b60f81b818381518110612c8c57612c8c6148c4565b60200101906001600160f81b031916908160001a905350612cae600a866143ce565b9450612c4e565b6000606060008060008661ffff166001600160401b03811115612cda57612cda613a6f565b6040519080825280601f01601f191660200182016040528015612d04576020820181803683370190505b50905060008087516020890160008d8df191503d925086831115612d26578692505b828152826000602083013e909890975095505050505050565b8180519060200120600360008761ffff1661ffff16815260200190815260200160002085604051612d7091906148da565b9081526040805191829003602090810183206001600160401b0388166000908152915220919091557fe183f33de2837795525b4792ca4cd60535bd77c53b7e7030060bfcf5734d6b0c9061159490879087908790879087906149dd565b60006001600160e01b031982166381af209b60e01b1480610c8c57506301ffc9a760e01b6001600160e01b0319831614610c8c565b600881901c600090815260209290925260409091208054600160ff1b60ff9093169290921c9091179055565b612e38338261233f565b612e925760405162461bcd60e51b815260206004820152602560248201527f73656e642063616c6c6572206973206e6f74206f776e6572206e6f72206170706044820152641c9bdd995960da1b6064820152608401610ac4565b836001600160a01b0316612ea582611628565b6001600160a01b031614612ef75760405162461bcd60e51b815260206004820152601960248201527839b2b73210333937b69034b731b7b93932b1ba1037bbb732b960391b6044820152606401610ac4565b6119ab84308361240c565b6000612f0d83613419565b61ffff808716600090815260016020908152604080832093891683529290529081205491925090612f3f9084906144ed565b905060008111612f8e5760405162461bcd60e51b815260206004820152601a602482015279131e905c1c0e881b5a5b91d85cd31a5b5a5d081b9bdd081cd95d60321b6044820152606401610ac4565b808210156117105760405162461bcd60e51b815260206004820152601b60248201527a4c7a4170703a20676173206c696d697420697320746f6f206c6f7760281b6044820152606401610ac4565b600454600090819061271090612ff69061ffff1685614399565b61300091906143ce565b905061300c81846146c1565b915080156130a8576004546040516000916201000090046001600160a01b03169083908381818185875af1925050503d8060008114613067576040519150601f19603f3d011682016040523d82523d6000602084013e61306c565b606091505b50509050806130a65760405162461bcd60e51b8152600401610ac4906020808252600490820152632166656560e01b604082015260600190565b505b50919050565b61ffff8616600090815260208190526040812080546130cc906142b3565b80601f01602080910402602001604051908101604052809291908181526020018280546130f8906142b3565b80156131455780601f1061311a57610100808354040283529160200191613145565b820191906000526020600020905b81548152906001019060200180831161312857829003601f168201915b505050505090508051600014156131b75760405162461bcd60e51b815260206004820152603060248201527f4c7a4170703a2064657374696e6174696f6e20636861696e206973206e6f742060448201526f61207472757374656420736f7572636560801b6064820152608401610ac4565b60405162c5803160e81b81526001600160a01b037f0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62169063c580310090849061320e908b9086908c908c908c908c90600401614a1b565b6000604051808303818588803b15801561322757600080fd5b505af115801561323b573d6000803e3d6000fd5b505050505050505050505050565b6000610c8c600983613474565b61325f816122b5565b158061328b575061326f816122b5565b801561328b57503061328082611628565b6001600160a01b0316145b61329457600080fd5b61329d816122b5565b6132ab57610f6b8282612b44565b610f6b30838361240c565b60006132c1600d5490565b90506132cd848461356c565b612b7b6000858386865b60006001600160a01b0385163b1561340d57506001835b6132f884866144ed565b81101561340757604051630a85bd0160e11b81526001600160a01b0387169063150b7a02906133319033908b9086908990600401614a82565b602060405180830381600087803b15801561334b57600080fd5b505af192505050801561337b575060408051601f3d908101601f1916820190925261337891810190614abf565b60015b6133d5573d8080156133a9576040519150601f19603f3d011682016040523d82523d6000602084013e6133ae565b606091505b5080516133cd5760405162461bcd60e51b8152600401610ac490614974565b805181602001fd5b8280156133f257506001600160e01b03198116630a85bd0160e11b145b925050806133ff8161456d565b9150506132ee565b5061220e565b50600195945050505050565b600060228251101561346c5760405162461bcd60e51b815260206004820152601c60248201527b4c7a4170703a20696e76616c69642061646170746572506172616d7360201b6044820152606401610ac4565b506022015190565b600881901c60008181526020849052604081205490919060ff808516919082181c80156134b6576134a4816136e5565b60ff168203600884901b179350613563565b600083116135235760405162461bcd60e51b815260206004820152603460248201527f4269744d6170733a205468652073657420626974206265666f7265207468652060448201527334b73232bc103237b2b9b713ba1032bc34b9ba1760611b6064820152608401610ac4565b50600019909101600081815260208690526040902054909190801561355e5761354b816136e5565b60ff0360ff16600884901b179350613563565b6134b6565b50505092915050565b6000613577600d5490565b9050600082116135d75760405162461bcd60e51b815260206004820152602560248201527f4552433732315073693a207175616e74697479206d7573742062652067726561604482015264074657220360dc1b6064820152608401610ac4565b6001600160a01b0383166136395760405162461bcd60e51b815260206004820152602360248201527f4552433732315073693a206d696e7420746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610ac4565b81600d600082825461364b91906144ed565b90915550506000818152600c6020526040902080546001600160a01b0319166001600160a01b038516179055613682600982612e02565b60008061368f84846144ed565b90506001600160a01b038516915082826000600080516020614afd833981519152600080a4600183015b8181146136df5780836000600080516020614afd833981519152600080a46001016136b9565b50610dc8565b60006040518061012001604052806101008152602001614b1d610100913960f87e818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff61372e8561374f565b02901c81518110613741576137416148c4565b016020015160f81c92915050565b600080821161375d57600080fd5b5060008190031690565b828054613773906142b3565b90600052602060002090601f01602090048101928261379557600085556137db565b82601f106137ae57805160ff19168380011785556137db565b828001600101855582156137db579182015b828111156137db5782518255916020019190600101906137c0565b506137e79291506137eb565b5090565b5b808211156137e757600081556001016137ec565b803561ffff8116811461381257600080fd5b919050565b60008083601f84011261382957600080fd5b5081356001600160401b0381111561384057600080fd5b60208301915083602082850101111561385857600080fd5b9250929050565b80356001600160401b038116811461381257600080fd5b6000806000806000806080878903121561388f57600080fd5b61389887613800565b955060208701356001600160401b03808211156138b457600080fd5b6138c08a838b01613817565b90975095508591506138d460408a0161385f565b945060608901359150808211156138ea57600080fd5b506138f789828a01613817565b979a9699509497509295939492505050565b6001600160e01b031981168114611a1657600080fd5b60006020828403121561393157600080fd5b813561393c81613909565b9392505050565b60005b8381101561395e578181015183820152602001613946565b838111156119ab5750506000910152565b60008151808452613987816020860160208601613943565b601f01601f19169290920160200192915050565b60208152600061393c602083018461396f565b6000602082840312156139c057600080fd5b61393c82613800565b6000602082840312156139db57600080fd5b5035919050565b6001600160a01b0381168114611a1657600080fd5b8035613812816139e2565b60008060408385031215613a1557600080fd5b8235613a20816139e2565b946020939093013593505050565b600080600060608486031215613a4357600080fd5b8335613a4e816139e2565b92506020840135613a5e816139e2565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613aad57613aad613a6f565b604052919050565b60006001600160401b03821115613ace57613ace613a6f565b50601f01601f191660200190565b600082601f830112613aed57600080fd5b8135613b00613afb82613ab5565b613a85565b818152846020838601011115613b1557600080fd5b816020850160208301376000918101602001919091529392505050565b8035801515811461381257600080fd5b600080600080600060a08688031215613b5a57600080fd5b613b6386613800565b945060208601356001600160401b0380821115613b7f57600080fd5b613b8b89838a01613adc565b955060408801359450613ba060608901613b32565b93506080880135915080821115613bb657600080fd5b50613bc388828901613adc565b9150509295509295909350565b60008060408385031215613be357600080fd5b50508035926020909101359150565b60006001600160401b03821115613c0b57613c0b613a6f565b5060051b60200190565b600082601f830112613c2657600080fd5b81356020613c36613afb83613bf2565b82815260059290921b84018101918181019086841115613c5557600080fd5b8286015b84811015613c705780358352918301918301613c59565b509695505050505050565b60008060008060008060c08789031215613c9457600080fd5b613c9d87613800565b955060208701356001600160401b0380821115613cb957600080fd5b613cc58a838b01613adc565b96506040890135915080821115613cdb57600080fd5b613ce78a838b01613c15565b9550613cf560608a01613b32565b94506080890135915080821115613d0b57600080fd5b613d178a838b01613adc565b935060a0890135915080821115613d2d57600080fd5b50613d3a89828a01613adc565b9150509295509295509295565b600080600060408486031215613d5c57600080fd5b613d6584613800565b925060208401356001600160401b03811115613d8057600080fd5b613d8c86828701613817565b9497909650939450505050565b600080600080600060808688031215613db157600080fd5b613dba86613800565b945060208601356001600160401b03811115613dd557600080fd5b613de188828901613817565b9699909850959660408101359660609091013595509350505050565b600080600080600080600060e0888a031215613e1857600080fd5b8735613e23816139e2565b9650613e3160208901613800565b955060408801356001600160401b0380821115613e4d57600080fd5b613e598b838c01613adc565b965060608a0135955060808a01359150613e72826139e2565b90935060a089013590613e84826139e2565b90925060c08901359080821115613e9a57600080fd5b50613ea78a828b01613adc565b91505092959891949750929550565b600060208284031215613ec857600080fd5b813562ffffff8116811461393c57600080fd5b600080600060608486031215613ef057600080fd5b613ef984613800565b925060208401356001600160401b03811115613f1457600080fd5b613f2086828701613adc565b925050613f2f6040850161385f565b90509250925092565b600060208284031215613f4a57600080fd5b813561393c816139e2565b60008060408385031215613f6857600080fd5b613f7183613800565b9150613f7f60208401613800565b90509250929050565b600060208284031215613f9a57600080fd5b81356001600160401b03811115613fb057600080fd5b61240484828501613adc565b60008060408385031215613fcf57600080fd5b613a2083613800565b60008060408385031215613feb57600080fd5b8235613ff6816139e2565b9150613f7f60208401613b32565b6000806000806080858703121561401a57600080fd5b8435614025816139e2565b93506020850135614035816139e2565b92506040850135915060608501356001600160401b0381111561405757600080fd5b61406387828801613adc565b91505092959194509250565b60008060008060008060008060006101208a8c03121561408e57600080fd5b6140978a6139f7565b98506140a560208b01613800565b975060408a01356001600160401b03808211156140c157600080fd5b6140cd8d838e01613adc565b985060608c01359150808211156140e357600080fd5b6140ef8d838e01613c15565b97506140fd60808d016139f7565b965061410b60a08d016139f7565b955060c08c013591508082111561412157600080fd5b61412d8d838e01613adc565b945060e08c013591508082111561414357600080fd5b61414f8d838e01613adc565b93506101008c013591508082111561416657600080fd5b506141738c828d01613adc565b9150509295985092959850929598565b60008060008060006080868803121561419b57600080fd5b6141a486613800565b94506141b260208701613800565b93506040860135925060608601356001600160401b038111156141d457600080fd5b6141e088828901613817565b969995985093965092949392505050565b60008060006060848603121561420657600080fd5b61420f84613800565b925061421d60208501613800565b9150604084013590509250925092565b6000806040838503121561424057600080fd5b823561424b816139e2565b9150602083013561425b816139e2565b809150509250929050565b6000806000806080858703121561427c57600080fd5b61428585613800565b935061429360208601613800565b925060408501356142a3816139e2565b9396929550929360600135925050565b600181811c908216806142c757607f821691505b602082108114156130a857634e487b7160e01b600052602260045260246000fd5b8183823760009101908152919050565b6020808252601e908201527f4c7a4170703a2063616c6c6572206973206e6f7420746865206f776e65720000604082015260600190565b60208082526034908201527f4552433732315073693a207472616e736665722063616c6c6572206973206e6f6040820152731d081bdddb995c881b9bdc88185c1c1c9bdd995960621b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156143b3576143b3614383565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826143dd576143dd6143b8565b500490565b600081518084526020808501945080840160005b83811015614412578151875295820195908201906001016143f6565b509495945050505050565b608081526000614430608083018761396f565b8281036020840152614442818761396f565b9050828103604084015261445681866143e2565b9050828103606084015261446a818561396f565b979650505050505050565b61ffff861681526001600160a01b038516602082015260a0604082018190526000906144a39083018661396f565b841515606084015282810360808401526144bd818561396f565b98975050505050505050565b600080604083850312156144dc57600080fd5b505080516020909101519092909150565b6000821982111561450057614500614383565b500190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b61ffff8416815260406020820152600061220e604083018486614505565b8284823760609190911b6001600160601b0319169101908152601401919050565b600060001982141561458157614581614383565b5060010190565b600082601f83011261459957600080fd5b81516145a7613afb82613ab5565b8181528460208386010111156145bc57600080fd5b612404826020830160208701613943565b600080600080608085870312156145e357600080fd5b84516001600160401b03808211156145fa57600080fd5b61460688838901614588565b955060209150818701518181111561461d57600080fd5b61462989828a01614588565b95505060408701518181111561463e57600080fd5b8701601f8101891361464f57600080fd5b805161465d613afb82613bf2565b81815260059190911b8201840190848101908b83111561467c57600080fd5b928501925b8284101561469a57835182529285019290850190614681565b60608b01519097509450505050808211156146b457600080fd5b5061406387828801614588565b6000828210156146d3576146d3614383565b500390565b8054600090600181811c90808316806146f257607f831692505b602080841082141561471457634e487b7160e01b600052602260045260246000fd5b818015614728576001811461473957614766565b60ff19861689528489019650614766565b60008881526020902060005b8681101561475e5781548b820152908501908301614745565b505084890196505b50505050505092915050565b60008451614784818460208901613943565b614790818401866146d8565b9050602f60f81b815283516147ac816001840160208801613943565b64173539b7b760d91b6001929091019182015260060195945050505050565b600061ffff80881683528087166020840152508460408301526080606083015261446a608083018486614505565b61ffff86168152608060208201526000614817608083018688614505565b6001600160401b0394909416604083015250606001529392505050565b60008351614846818460208801613943565b61220e818401856146d8565b60006020828403121561486457600080fd5b81516001600160401b0381111561487a57600080fd5b61240484828501614588565b61ffff851681526080602082015260006148a3608083018661396f565b6001600160401b0385166040840152828103606084015261446a818561396f565b634e487b7160e01b600052603260045260246000fd5b600082516148ec818460208701613943565b9190910192915050565b60208152600061393c60208301846143e2565b828152604060208201526000612404604083018461396f565b61ffff8616815260a06020820152600061493f60a083018761396f565b6001600160a01b0386166040840152828103606084015261496081866143e2565b905082810360808401526144bd818561396f565b60208082526035908201527f4552433732315073693a207472616e7366657220746f206e6f6e20455243373260408201527418a932b1b2b4bb32b91034b6b83632b6b2b73a32b960591b606082015260800190565b6000826149d8576149d86143b8565b500690565b61ffff8616815260a0602082015260006149fa60a083018761396f565b6001600160401b03861660408401528281036060840152614960818661396f565b61ffff8716815260c060208201526000614a3860c083018861396f565b8281036040840152614a4a818861396f565b6001600160a01b0387811660608601528616608085015283810360a08501529050614a75818561396f565b9998505050505050505050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614ab59083018461396f565b9695505050505050565b600060208284031215614ad157600080fd5b815161393c8161390956fe8c0400cfe2d1199b1a725c78960bcc2a344d869b80590d0f2bd005db15a572ceddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8a26469706673582212205419fe7d71e8c77355e02a9e369bccd3b08210e7c851dd210beebbe96d0cd76364736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000f285e70ca2002b796a575e473285282bbf39d790000000000000000000000000000000000000000000000000000000000003d0900000000000000000000000003c2269811836af69497e5f486a85d7316753cf6200000000000000000000000000000000000000000000000000000000000000105a6b616c69656e204578706c6f7265720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a4b580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b6261666b726569677a346773623472326263756e736468377532736233717233686667646f6868796d73697774703271636177746b616d367264610000000000000000000000000000000000000000000000000000000000000000000000003b6261667962656966746d756f786e686c6d6d6f62666872616c6c69616233707471757764787033646a6979343261357067643236326f6d6a3335710000000000
-----Decoded View---------------
Arg [0] : _name (string): Zkalien Explorer
Arg [1] : _symbol (string): ZKX
Arg [2] : _collectionURI (string): bafkreigz4gsb4r2bcunsdh7u2sb3qr3hfgdohhymsiwtp2qcawtkam6rda
Arg [3] : _tokensURI (string): bafybeiftmuoxnhlmmobfhralliab3ptquwdxp3djiy42a5pgd262omj35q
Arg [4] : _owner (address): 0xF285E70Ca2002b796A575E473285282BBf39D790
Arg [5] : _minGasToTransfer (uint256): 250000
Arg [6] : _lzEndpoint (address): 0x3c2269811836af69497E5F486A85D7316753cf62
-----Encoded View---------------
17 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000160
Arg [3] : 00000000000000000000000000000000000000000000000000000000000001c0
Arg [4] : 000000000000000000000000f285e70ca2002b796a575e473285282bbf39d790
Arg [5] : 000000000000000000000000000000000000000000000000000000000003d090
Arg [6] : 0000000000000000000000003c2269811836af69497e5f486a85d7316753cf62
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000010
Arg [8] : 5a6b616c69656e204578706c6f72657200000000000000000000000000000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [10] : 5a4b580000000000000000000000000000000000000000000000000000000000
Arg [11] : 000000000000000000000000000000000000000000000000000000000000003b
Arg [12] : 6261666b726569677a346773623472326263756e736468377532736233717233
Arg [13] : 686667646f6868796d73697774703271636177746b616d367264610000000000
Arg [14] : 000000000000000000000000000000000000000000000000000000000000003b
Arg [15] : 6261667962656966746d756f786e686c6d6d6f62666872616c6c696162337074
Arg [16] : 71757764787033646a6979343261357067643236326f6d6a3335710000000000
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.