ERC-721
Source Code
NFT
Overview
Max Total Supply
10,000 LUCHADORES
Holders
1,730
Transfers
-
4
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
| # | Exchange | Pair | Price | 24H Volume | % Volume |
|---|
Contract Name:
Luchadores
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "@openzeppelin/contracts/token/ERC721/ERC721Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@chainlink/contracts/src/v0.6/VRFConsumerBase.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
contract Luchadores is ERC721Pausable, Ownable, ReentrancyGuard, VRFConsumerBase {
using Counters for Counters.Counter;
using Strings for uint256;
Counters.Counter private _tokenIds;
IUniswapV2Router02 public uniswapRouter;
bytes32 internal keyHash = 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445;
uint256 internal LinkFee = 2 * 10**18; // 2 LINK
address private VRFCoordinator = 0xf0d54349aDdcf704F77AE15b96510dEA15cb7952;
address private LinkToken = 0x514910771AF9Ca656af840dff83E8264EcF986CA;
constructor() public
ERC721("Luchadores", "LUCHADORES")
VRFConsumerBase(VRFCoordinator, LinkToken)
{
uniswapRouter = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
art.baseColor = ["ebebf7", "1c1d2f", "cc0d3d", "d22f94", "890ec1", "1c49d8", "19b554", "13cac6", "f7c23c", "f18e2f"];
art.altColor = ["dadae6", "13141f", "ea184d", "e0369f", "9511d2", "2854e6", "1da951", "11b9b5", "e8b63a", "e28327"];
art.eyeColor = ["3b6ba5", "3b8fa5", "3ba599", "3ba577", "339842", "7fa53b", "a5823b", "a5693b", "844f1d", "4e2906"];
art.skinColor = ["f9d1b7", "f7b897", "f39c77", "ffcb84", "bd7e47", "b97e4b", "b97a50", "5a3214", "50270e", "3a1b09"];
art.spirit[0] = Item("Bull", "<path fill='#A9A18A' d='M21 2V1h-1V0h-1v2h1v1h-3v2h2v1h2V5h1V2zM5 3H4V2h1V0H4v1H3v1H2v3h1v1h2V5h2V3H6z'/><g fill='#000' opacity='.15'><path d='M21 4h1v1h-1zM19 5h-1v1h3V5h-1z'/><path d='M2 4h1v1H2zM4 5H3v1h3V5H5z'/></g>");
art.spirit[1] = Item("Jaguar", "<path class='lucha-base' d='M6 2V1H5v5h1V5h1V3h1V2H7zM18 1v1h-2v1h1v2h1v1h1V1z'/><g fill='#000'><path d='M5 1h1v1H5zM6 2v1h2V2H7zM18 1h1v1h-1zM16 2v1h2V2h-1z' opacity='.3'/><path d='M6 3V2H5v4h1V5h1V3zM18 2v1h-1v2h1v1h1V2z' opacity='.2'/></g>");
art.cape[0] = Item("Classic", "<path class='lucha-alt' d='M20 11H3v12h1v-1h2v-1h12v1h2v1h1V11z'/><g fill='#000'><path opacity='.2' d='M20 11v12h1V11zM3 12v11h1V11H3z'/><path opacity='.5' d='M19 11H4v11h2v-1h12v1h2V11z'/></g>");
art.cape[1] = Item("Hooded", "<path class='lucha-alt' d='M20 11H3v12h1v-1h2v-1h12v1h2v1h1V11z'/><g fill='#000'><path opacity='.2' d='M20 11v12h1V11zM3 12v11h1V11H3z'/><path opacity='.5' d='M19 11H4v11h2v-1h12v1h2V11z'/></g>");
art.torso[0] = Item("Shirt", "<path class='lucha-base' d='M22 12v-1h-1v-1h-1V9H4v1H3v1H2v1H1v5h4v-3h1v1h1v1h1v2h8v-2h1v-1h1v-1h1v3h4v-5z'/><path d='M22 12v-1h-1v-1h-1V9H4v1H3v1H2v1H1v5h4v-3h1v1h1v1h1v2h8v-2h1v-1h1v-1h1v3h4v-5z' fill='#000' opacity='.15'/>");
art.torso[1] = Item("Open Shirt", "<path class='lucha-base' d='M10 9H4v1H3v1H2v1H1v3h4v-1h1v1h1v1h1v2h3V9zM22 12v-1h-1v-1h-1V9h-7v9h3v-2h1v-1h1v-1h1v1h4v-3z'/><path d='M10 9H4v1H3v1H2v1H1v3h4v-1h1v1h1v1h1v2h3V9zM22 12v-1h-1v-1h-1V9h-7v9h3v-2h1v-1h1v-1h1v1h4v-3z' fill='#000' opacity='.15'/>");
art.torso[2] = Item("Singlet", "<path class='lucha-base' d='M16 9H7v3h1-1v4h1v1h8v-1h1v-4h-1 1V9z'/><path fill='#000' opacity='.15' d='M16 9H7v7h1v1h8v-1h1V9z'/>");
art.torso[3] = Item("Suspenders", "<path class='lucha-base' d='M15 9v9h1V9zM8 10v8h1V9H8z'/><path d='M8 10v8h1V9H8zM15 9v9h1V9z' fill='#000' opacity='.15'/>");
art.arms[0] = Item("Gloves", "<path class='lucha-base' d='M5 16H1v3h4v-1h1v-1H5zM22 16h-3v1h-1v1h1v1h4v-3z'/><path class='lucha-alt' d='M3 16H1v1h4v-1H4zM22 16h-3v1h4v-1z'/>");
art.arms[1] = Item("Wrist Bands", "<path class='lucha-base' d='M3 15H1v2h4v-2H4zM22 15h-3v2h4v-2z'/>");
art.arms[2] = Item("Right Band", "<path class='lucha-alt' d='M4 14H1v1h4v-1z'/>");
art.arms[3] = Item("Left Band", "<path class='lucha-base' d='M22 14h-3v1h4v-1z'/>");
art.arms[4] = Item("Arm Bands", "<path class='lucha-base' d='M4 14H1v1h4v-1zM22 14h-3v1h4v-1z'/>");
art.arms[5] = Item("Sleeves", "<path class='lucha-base' d='M22 14h-3v3h4v-3zM3 14H1v3h4v-3H4z'/><path class='lucha-alt' d='M22 14h-3v1h4v-1zM3 14H1v1h4v-1H4z'/>");
art.mask[0] = Item("Split", "<path d='M11 0H9v1H8v1H7v1H6v2H5v5h1v2h1v1h1v1h1v1h3V0z'/>");
art.mask[1] = Item("Cross", "<path d='M14 2h-1V0h-2v2H9v2h2v4h2V4h2V2zM12 13h-1v2h2v-2z'/>");
art.mask[2] = Item("Fierce", "<path d='M17 3v1h-2v1h-1v1h-1v3h5V3zM11 8V6h-1V5H9V4H7V3H6v6h5zM11 13v2h2v-2h-1z'/>");
art.mask[3] = Item("Striped", "<path d='M11 2h2V1h1V0h-4v1h1zM6 10v2h1v-1h1v-1H7zM17 10h-1v1h1v1h1v-2z'/><path d='M16 3h1V2h-1V1h-1v1h-1v1h-1v1h-2V3h-1V2H9V1H8v1H7v1h1v1h1v1h1v1h1v9h2V6h1V5h1V4h1z'/>");
art.mask[4] = Item("Bolt", "<path d='M13 3h-3V2h1V1h1V0H9v1H8v1H7v1H6v2h3v1H8v2H7v2h1V9h1V8h1V7h1V6h1V5h1V4h1V3z'/>");
art.mask[5] = Item("Winged", "<path d='M18 5V3h-1V2h-1v1h-1v1h-1v1h-1v1h-2V5h-1V4H9V3H8V2H7v1H6v2H5v5h1v2h1v-1h1v-1h3V9h2v1h3v1h1v1h1v-2h1V5z'/>");
art.mask[6] = Item("Classic", "<path d='M18 5V3h-1V2h-1v2h-1v1h-1v1h-1v3h-2V6h-1V5H9V4H8V2H7v1H6v2H5v4h1v1h2v3h1v1h6v-1h1v-3h2V9h1V5z'/>");
art.mask[7] = Item("Arrow", "<path d='M18 5V3h-1V2h-1V1h-1V0H9v1H8v1H7v1H6v2H5v5h1v2h1v1h1v1h1v1h1v-4h1V5H9V3h1V2h1V1h2v1h1v1h1v2h-2v6h1v4h1v-1h1v-1h1v-1h1v-2h1V5z'/>");
art.mask[8] = Item("Dash", "<path d='M13 3V2h-2v2h2zM13 1V0h-2v1h1zM10 4H9V1H8v1H7v1H6v2H5v5h1v2h1v1h1v1h1v1h1v-2H9v-3h2V5h-1zM18 5V3h-1V2h-1V1h-1v3h-1v1h-1v5h2v3h-1v2h1v-1h1v-1h1v-1h1v-2h1V5z'/>");
art.mouth[0] = Item("Moustache", "<path fill='#421c03' opacity='.9' d='M14 10H9v3h1v-2h4v2h1v-3z'/>");
art.bottoms[0] = Item("Tights", "<path class='lucha-alt' d='M15 17H8v6h3v-3h2v3h3v-6z'/>");
art.bottoms[1] = Item("Trunk Tights", "<path class='lucha-base' d='M15 17H8v3h8v-3z'/><path class='lucha-alt' d='M15 18v1h-2v4h3v-5zM9 19v-1H8v5h3v-4h-1z'/>");
art.boots[0] = Item("Two Tone", "<path class='lucha-alt' d='M9 22H8v1H7v1h4v-2h-1zM16 23v-1h-3v2h4v-1z'/>");
art.boots[1] = Item("High", "<path class='lucha-alt' d='M9 20H8v1h3v-1h-1zM15 20h-2v1h3v-1z'/>");
}
struct Item {
bytes12 name;
string svg;
}
struct Art {
string[] baseColor;
string[] altColor;
string[] eyeColor;
string[] skinColor;
mapping(uint256 => Item) spirit;
mapping(uint256 => Item) cape;
mapping(uint256 => Item) torso;
mapping(uint256 => Item) arms;
mapping(uint256 => Item) mask;
mapping(uint256 => Item) mouth;
mapping(uint256 => Item) bottoms;
mapping(uint256 => Item) boots;
}
Art art;
struct Luchador {
uint256 dna;
}
struct VRFRequest {
uint256 id;
}
mapping(uint256 => Luchador) luchadores;
mapping(bytes32 => VRFRequest) VRFRequests;
event GenerateLuchador(
uint256 indexed id,
uint256 dna
);
function generateLuchador(uint256 _quantity, uint256 _deadline) external payable nonReentrant whenNotPaused {
require(_tokenIds.current() < 10000, "maximum luchadores reached");
require(_tokenIds.current() + _quantity <= 10000, "mint quantity exceeds max supply");
require(_quantity > 0 && _quantity <= 20, "mint quantity must be between 1-20");
uint256 amountOut = LinkFee * _quantity;
address[] memory path = new address[](2);
path[0] = uniswapRouter.WETH();
path[1] = LinkToken;
uniswapRouter.swapETHForExactTokens{value: msg.value}(amountOut, path, address(this), _deadline);
for (uint256 i = 0; i < _quantity; i++) {
getRandomNumber(uint256(blockhash(block.number - i)));
}
}
function getRandomNumber(uint256 _userProvidedSeed) internal {
require(LINK.balanceOf(address(this)) >= LinkFee, "Not enough LINK - fill contract");
bytes32 requestId = requestRandomness(keyHash, LinkFee, _userProvidedSeed);
_tokenIds.increment();
VRFRequests[requestId] = VRFRequest({
id: _tokenIds.current()
});
_safeMint(msg.sender, _tokenIds.current());
}
function fulfillRandomness(bytes32 _requestId, uint256 _randomNumber) internal override {
luchadores[VRFRequests[_requestId].id].dna = _randomNumber;
emit GenerateLuchador(VRFRequests[_requestId].id, _randomNumber);
}
function imageData(uint256 _tokenId) public view returns (string memory) {
require(_exists(_tokenId), "imageData: nonexistent token");
require(luchadores[_tokenId].dna != 0, "imageData: dna not yet generated");
uint8[12] memory dna = splitNumber(luchadores[_tokenId].dna);
string memory capeShoulders = (dna[1] == 0 || dna[1] == 1)? "<path class='lucha-alt' d='M20 10V9h-2v1h-1v1h4v-1zM5 9H4v1H3v1h4v-1H6V9z'/><path fill='#000' opacity='.2' d='M6 9H4v1H3v1h4v-1H6zM20 10V9h-2v1h-1v1h4v-1z'/>" : "";
string memory capeHood = dna[1] == 1 ? "<path class='lucha-alt' d='M18 4V3h-1V2h-1V1h-1V0H9v1H8v1H7v1H6v2H5v5h1V6h1V5h2V4h1V3h4v1h1v1h2v1h1v4h1V5h-1z'/><g fill='#000'><path d='M18 4V3h-1V2h-1V1h-1V0H9v1H8v1H7v1H6v2H5v5h1V5h1V4h1V3h1V2h6v1h1v1h1v1h1v5h1V5h-1z' opacity='.2'/><path d='M16 4V3h-1V2H9v1H8v1H7v1h2V4h1V3h4v1h1v1h2V4zM6 5h1v1H6zM17 5h1v1h-1z' opacity='.5'/></g>" : "";
return string(abi.encodePacked(
"<svg id='luchador", _tokenId.toString(), "' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'>",
styles(_tokenId, dna),
"<g class='lucha-breathe'>",
art.spirit[dna[0]].svg,
art.cape[dna[1]].svg,
"<path class='lucha-skin' d='M22 12v-1h-1v-1h-1V9h-1V5h-1V3h-1V2h-1V1h-1V0H9v1H8v1H7v1H6v2H5v4H4v1H3v1H2v1H1v8h4v-1h1v-2H5v-3h1v1h1v1h1v2h8v-2h1v-1h1v-1h1v3h-1v2h1v1h4v-8z'/>",
art.torso[dna[2]].svg,
art.arms[dna[3]].svg,
capeShoulders,
"<path class='lucha-base' d='M18 5V3h-1V2h-1V1h-1V0H9v1H8v1H7v1H6v2H5v5h1v2h1v1h1v1h1v1h6v-1h1v-1h1v-1h1v-2h1V5z'/>",
"<g class='lucha-alt'>", art.mask[dna[4]].svg, "</g>",
capeHood,
"<path fill='#FFF' d='M9 6H6v3h4V6zM17 6h-3v3h4V6z'/><path class='lucha-eyes' d='M16 6h-2v3h3V6zM8 6H7v3h3V6H9z'/><path fill='#FFF' d='M7 6h1v1H7zM16 6h1v1h-1z' opacity='.4'/><path fill='#000' d='M15 7h1v1h-1zM8 7h1v1H8z'/>",
"<path class='lucha-skin' d='M14 10H9v3h6v-3z'/>",
"<path fill='#000' opacity='.9' d='M13 11h-3v1h4v-1z'/>",
art.mouth[dna[5]].svg,
"</g>",
"<path class='lucha-skin' d='M16 23v-6H8v6H7v1h4v-4h2v4h4v-1z'/>",
"<path class='lucha-base' d='M15 17H8v1h1v1h2v1h2v-1h2v-1h1v-1z'/>",
art.bottoms[dna[6]].svg,
"<path class='lucha-base' d='M9 21H8v2H7v1h4v-3h-1zM16 23v-2h-3v3h4v-1z'/>",
art.boots[dna[7]].svg,
"</svg>"
));
}
function styles(uint256 _tokenId, uint8[12] memory _dna) internal view returns (string memory) {
return string(abi.encodePacked(
"<style>#luchador", _tokenId.toString(), " .lucha-base { fill: #", art.baseColor[_dna[8]],
"; } #luchador", _tokenId.toString(), " .lucha-alt { fill: #", art.altColor[_dna[9]],
"; } #luchador", _tokenId.toString(), " .lucha-eyes { fill: #", art.eyeColor[_dna[10]],
"; } #luchador", _tokenId.toString(), " .lucha-skin { fill: #", art.skinColor[_dna[11]],
"; } #luchador", _tokenId.toString(), " .lucha-breathe { animation: 0.5s lucha-breathe infinite alternate ease-in-out; } @keyframes lucha-breathe { from { transform: translateY(0px); } to { transform: translateY(1%); } }</style>"
));
}
function metadata(uint256 _tokenId) public view returns (string memory) {
require(_exists(_tokenId), "metadata: nonexistent token");
require(luchadores[_tokenId].dna != 0, "metadata: dna not yet generated");
uint8[12] memory dna = splitNumber(luchadores[_tokenId].dna);
Item[8] memory artItems = [
art.spirit[dna[0]],
art.cape[dna[1]],
art.torso[dna[2]],
art.arms[dna[3]],
art.mask[dna[4]],
art.mouth[dna[5]],
art.bottoms[dna[6]],
art.boots[dna[7]]
];
string memory attributes;
string[8] memory traitType = ["Spirit", "Cape", "Torso", "Arms", "Mask", "Mouth", "Bottoms", "Boots"];
for (uint256 i = 0; i < artItems.length; i++) {
if (artItems[i].name == "") continue;
attributes = string(abi.encodePacked(attributes,
bytes(attributes).length == 0 ? '{' : ', {',
'"trait_type": "', traitType[i],'",',
'"value": "', bytes12ToString(artItems[i].name), '"',
'}'
));
}
return string(abi.encodePacked(
'{',
'"name": "Luchador #', _tokenId.toString(), '",',
'"description": "Luchadores are randomly generated using Chainlink VRF and have 100% on-chain art and metadata - Only 10000 will ever exist!",',
'"image_data": "', imageData(_tokenId), '",',
'"external_url": "https://luchadores.io/luchador/', _tokenId.toString(), '",',
'"attributes": [', attributes, ']',
'}'
));
}
function splitNumber(uint256 _number) internal pure returns (uint8[12] memory) {
uint8[12] memory numbers;
for (uint256 i = 0; i < numbers.length; i++) {
numbers[i] = uint8(_number % 10);
_number /= 10;
}
return numbers;
}
function bytes12ToString(bytes12 _bytes12) internal pure returns (string memory) {
uint8 i = 0;
while(i < 12 && _bytes12[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 12 && _bytes12[i] != 0; i++) {
bytesArray[i] = _bytes12[i];
}
return string(bytesArray);
}
function pauseSale() public onlyOwner {
_pause();
}
function unpauseSale() public onlyOwner {
_unpause();
}
function setLinkFee(uint256 _LinkFee) public onlyOwner {
LinkFee = _LinkFee;
}
function setBaseURI(string memory _baseURI) public onlyOwner {
_setBaseURI(_baseURI);
}
function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) {
require(_exists(_tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = baseURI();
return bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, _tokenId.toString(), ".json"))
: '';
}
function withdraw() public onlyOwner {
(bool success, ) = msg.sender.call{value: address(this).balance}('');
require(success, "Withdrawal failed");
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "./vendor/SafeMathChainlink.sol";
import "./interfaces/LinkTokenInterface.sol";
import "./VRFRequestIDBase.sol";
/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
* @dev PURPOSE
*
* @dev Reggie the Random Oracle (not his real job) wants to provide randomness
* @dev to Vera the verifier in such a way that Vera can be sure he's not
* @dev making his output up to suit himself. Reggie provides Vera a public key
* @dev to which he knows the secret key. Each time Vera provides a seed to
* @dev Reggie, he gives back a value which is computed completely
* @dev deterministically from the seed and the secret key.
*
* @dev Reggie provides a proof by which Vera can verify that the output was
* @dev correctly computed once Reggie tells it to her, but without that proof,
* @dev the output is indistinguishable to her from a uniform random sample
* @dev from the output space.
*
* @dev The purpose of this contract is to make it easy for unrelated contracts
* @dev to talk to Vera the verifier about the work Reggie is doing, to provide
* @dev simple access to a verifiable source of randomness.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFConsumerBase, and can
* @dev initialize VRFConsumerBase's attributes in their constructor as
* @dev shown:
*
* @dev contract VRFConsumer {
* @dev constuctor(<other arguments>, address _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator, _link) public {
* @dev <initialization with other arguments goes here>
* @dev }
* @dev }
*
* @dev The oracle will have given you an ID for the VRF keypair they have
* @dev committed to (let's call it keyHash), and have told you the minimum LINK
* @dev price for VRF service. Make sure your contract has sufficient LINK, and
* @dev call requestRandomness(keyHash, fee, seed), where seed is the input you
* @dev want to generate randomness from.
*
* @dev Once the VRFCoordinator has received and validated the oracle's response
* @dev to your request, it will call your contract's fulfillRandomness method.
*
* @dev The randomness argument to fulfillRandomness is the actual random value
* @dev generated from your seed.
*
* @dev The requestId argument is generated from the keyHash and the seed by
* @dev makeRequestId(keyHash, seed). If your contract could have concurrent
* @dev requests open, you can use the requestId to track which seed is
* @dev associated with which randomness. See VRFRequestIDBase.sol for more
* @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind,
* @dev if your contract could have multiple requests in flight simultaneously.)
*
* @dev Colliding `requestId`s are cryptographically impossible as long as seeds
* @dev differ. (Which is critical to making unpredictable randomness! See the
* @dev next section.)
*
* *****************************************************************************
* @dev SECURITY CONSIDERATIONS
*
* @dev A method with the ability to call your fulfillRandomness method directly
* @dev could spoof a VRF response with any random value, so it's critical that
* @dev it cannot be directly called by anything other than this base contract
* @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
*
* @dev For your users to trust that your contract's random behavior is free
* @dev from malicious interference, it's best if you can write it so that all
* @dev behaviors implied by a VRF response are executed *during* your
* @dev fulfillRandomness method. If your contract must store the response (or
* @dev anything derived from it) and use it later, you must ensure that any
* @dev user-significant behavior which depends on that stored value cannot be
* @dev manipulated by a subsequent VRF request.
*
* @dev Similarly, both miners and the VRF oracle itself have some influence
* @dev over the order in which VRF responses appear on the blockchain, so if
* @dev your contract could have multiple VRF requests in flight simultaneously,
* @dev you must ensure that the order in which the VRF responses arrive cannot
* @dev be used to manipulate your contract's user-significant behavior.
*
* @dev Since the ultimate input to the VRF is mixed with the block hash of the
* @dev block in which the request is made, user-provided seeds have no impact
* @dev on its economic security properties. They are only included for API
* @dev compatability with previous versions of this contract.
*
* @dev Since the block hash of the block which contains the requestRandomness
* @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
* @dev miner could, in principle, fork the blockchain to evict the block
* @dev containing the request, forcing the request to be included in a
* @dev different block with a different hash, and therefore a different input
* @dev to the VRF. However, such an attack would incur a substantial economic
* @dev cost. This cost scales with the number of blocks the VRF oracle waits
* @dev until it calls responds to a request.
*/
abstract contract VRFConsumerBase is VRFRequestIDBase {
using SafeMathChainlink for uint256;
/**
* @notice fulfillRandomness handles the VRF response. Your contract must
* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
* @notice principles to keep in mind when implementing your fulfillRandomness
* @notice method.
*
* @dev VRFConsumerBase expects its subcontracts to have a method with this
* @dev signature, and will call it once it has verified the proof
* @dev associated with the randomness. (It is triggered via a call to
* @dev rawFulfillRandomness, below.)
*
* @param requestId The Id initially returned by requestRandomness
* @param randomness the VRF output
*/
function fulfillRandomness(bytes32 requestId, uint256 randomness)
internal virtual;
/**
* @notice requestRandomness initiates a request for VRF output given _seed
*
* @dev The fulfillRandomness method receives the output, once it's provided
* @dev by the Oracle, and verified by the vrfCoordinator.
*
* @dev The _keyHash must already be registered with the VRFCoordinator, and
* @dev the _fee must exceed the fee specified during registration of the
* @dev _keyHash.
*
* @dev The _seed parameter is vestigial, and is kept only for API
* @dev compatibility with older versions. It can't *hurt* to mix in some of
* @dev your own randomness, here, but it's not necessary because the VRF
* @dev oracle will mix the hash of the block containing your request into the
* @dev VRF seed it ultimately uses.
*
* @param _keyHash ID of public key against which randomness is generated
* @param _fee The amount of LINK to send with the request
* @param _seed seed mixed into the input of the VRF.
*
* @return requestId unique ID for this request
*
* @dev The returned requestId can be used to distinguish responses to
* @dev concurrent requests. It is passed as the first argument to
* @dev fulfillRandomness.
*/
function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed)
internal returns (bytes32 requestId)
{
LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, _seed));
// This is the seed passed to VRFCoordinator. The oracle will mix this with
// the hash of the block containing this request to obtain the seed/input
// which is finally passed to the VRF cryptographic machinery.
uint256 vRFSeed = makeVRFInputSeed(_keyHash, _seed, address(this), nonces[_keyHash]);
// nonces[_keyHash] must stay in sync with
// VRFCoordinator.nonces[_keyHash][this], which was incremented by the above
// successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest).
// This provides protection against the user repeating their input seed,
// which would result in a predictable/duplicate output, if multiple such
// requests appeared in the same block.
nonces[_keyHash] = nonces[_keyHash].add(1);
return makeRequestId(_keyHash, vRFSeed);
}
LinkTokenInterface immutable internal LINK;
address immutable private vrfCoordinator;
// Nonces for each VRF key from which randomness has been requested.
//
// Must stay in sync with VRFCoordinator[_keyHash][this]
mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
* @param _link address of LINK token contract
*
* @dev https://docs.chain.link/docs/link-token-contracts
*/
constructor(address _vrfCoordinator, address _link) public {
vrfCoordinator = _vrfCoordinator;
LINK = LinkTokenInterface(_link);
}
// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
// the origin of the call
function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external {
require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
fulfillRandomness(requestId, randomness);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract VRFRequestIDBase {
/**
* @notice returns the seed which is actually input to the VRF coordinator
*
* @dev To prevent repetition of VRF output due to repetition of the
* @dev user-supplied seed, that seed is combined in a hash with the
* @dev user-specific nonce, and the address of the consuming contract. The
* @dev risk of repetition is mostly mitigated by inclusion of a blockhash in
* @dev the final seed, but the nonce does protect against repetition in
* @dev requests which are included in a single block.
*
* @param _userSeed VRF seed input provided by user
* @param _requester Address of the requesting contract
* @param _nonce User-specific nonce at the time of the request
*/
function makeVRFInputSeed(bytes32 _keyHash, uint256 _userSeed,
address _requester, uint256 _nonce)
internal pure returns (uint256)
{
return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
}
/**
* @notice Returns the id for this request
* @param _keyHash The serviceAgreement ID to be used for this request
* @param _vRFInputSeed The seed to be passed directly to the VRF
* @return The id for this request
*
* @dev Note that _vRFInputSeed is not the seed passed by the consuming
* @dev contract, but the one generated by makeVRFInputSeed
*/
function makeRequestId(
bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
function transferFrom(address from, address to, uint256 value) external returns (bool success);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMathChainlink {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
abstract contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <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.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC721.sol";
import "./IERC721Metadata.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Receiver.sol";
import "../../introspection/ERC165.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../../utils/EnumerableSet.sol";
import "../../utils/EnumerableMap.sol";
import "../../utils/Strings.sol";
/**
* @title ERC721 Non-Fungible Token Standard basic implementation
* @dev see https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Enumerable {
using SafeMath for uint256;
using Address for address;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableMap for EnumerableMap.UintToAddressMap;
using Strings for uint256;
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
// Mapping from holder address to their (enumerable) set of owned tokens
mapping (address => EnumerableSet.UintSet) private _holderTokens;
// Enumerable mapping from token ids to their owners
EnumerableMap.UintToAddressMap private _tokenOwners;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Optional mapping for token URIs
mapping (uint256 => string) private _tokenURIs;
// Base URI
string private _baseURI;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/*
* bytes4(keccak256('totalSupply()')) == 0x18160ddd
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
*
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
*/
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721);
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _holderTokens[owner].length();
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
// If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI.
return string(abi.encodePacked(base, tokenId.toString()));
}
/**
* @dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a prefix in {tokenURI} to each token's URI, or
* to the token ID if no specific URI is set for that token ID.
*/
function baseURI() public view virtual returns (string memory) {
return _baseURI;
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
return _holderTokens[owner].at(index);
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
// _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
return _tokenOwners.length();
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
(uint256 tokenId, ) = _tokenOwners.at(index);
return tokenId;
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || ERC721.isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _tokenOwners.contains(tokenId);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || ERC721.isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
d*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId); // internal owner
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
_holderTokens[owner].remove(tokenId);
_tokenOwners.remove(tokenId);
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_holderTokens[from].remove(tokenId);
_holderTokens[to].add(tokenId);
_tokenOwners.set(tokenId, to);
emit Transfer(from, to, tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI},
* or to the token ID if {tokenURI} is empty.
*/
function _setBaseURI(string memory baseURI_) internal virtual {
_baseURI = baseURI_;
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes memory returndata = to.functionCall(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
), "ERC721: transfer to non ERC721Receiver implementer");
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./ERC721.sol";
import "../../utils/Pausable.sol";
/**
* @dev ERC721 token with pausable token transfers, minting and burning.
*
* Useful for scenarios such as preventing trades until the end of an evaluation
* period, or having an emergency switch for freezing all token transfers in the
* event of a large bug.
*/
abstract contract ERC721Pausable is ERC721, Pausable {
/**
* @dev See {ERC721-_beforeTokenTransfer}.
*
* Requirements:
*
* - the contract must not be paused.
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
require(!paused(), "ERC721Pausable: token transfer while paused");
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "../../introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../math/SafeMath.sol";
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
library Counters {
using SafeMath for uint256;
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
// The {SafeMath} overflow check can be skipped here, see the comment at the top
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
* supported.
*/
library EnumerableMap {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct MapEntry {
bytes32 _key;
bytes32 _value;
}
struct Map {
// Storage of map keys and values
MapEntry[] _entries;
// Position of the entry defined by a key in the `entries` array, plus 1
// because index 0 means a key is not in the map.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
// We read and store the key's index to prevent multiple reads from the same storage slot
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) { // Equivalent to !contains(map, key)
map._entries.push(MapEntry({ _key: key, _value: value }));
// The entry is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
map._indexes[key] = map._entries.length;
return true;
} else {
map._entries[keyIndex - 1]._value = value;
return false;
}
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function _remove(Map storage map, bytes32 key) private returns (bool) {
// We read and store the key's index to prevent multiple reads from the same storage slot
uint256 keyIndex = map._indexes[key];
if (keyIndex != 0) { // Equivalent to contains(map, key)
// To delete a key-value pair from the _entries array in O(1), we swap the entry to delete with the last one
// in the array, and then remove the last entry (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = keyIndex - 1;
uint256 lastIndex = map._entries.length - 1;
// When the entry to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
MapEntry storage lastEntry = map._entries[lastIndex];
// Move the last entry to the index where the entry to delete is
map._entries[toDeleteIndex] = lastEntry;
// Update the index for the moved entry
map._indexes[lastEntry._key] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved entry was stored
map._entries.pop();
// Delete the index for the deleted slot
delete map._indexes[key];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._indexes[key] != 0;
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function _length(Map storage map) private view returns (uint256) {
return map._entries.length;
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
require(map._entries.length > index, "EnumerableMap: index out of bounds");
MapEntry storage entry = map._entries[index];
return (entry._key, entry._value);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) return (false, 0); // Equivalent to contains(map, key)
return (true, map._entries[keyIndex - 1]._value); // All indexes are 1-based
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, "EnumerableMap: nonexistent key"); // Equivalent to contains(map, key)
return map._entries[keyIndex - 1]._value; // All indexes are 1-based
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
*/
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
require(keyIndex != 0, errorMessage); // Equivalent to contains(map, key)
return map._entries[keyIndex - 1]._value; // All indexes are 1-based
}
// UintToAddressMap
struct UintToAddressMap {
Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*
* _Available since v3.4._
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor () internal {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev String operations.
*/
library Strings {
/**
* @dev Converts a `uint256` to its ASCII `string` representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = bytes1(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}pragma solidity >=0.6.2;
import './IUniswapV2Router01.sol';
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "istanbul",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"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":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dna","type":"uint256"}],"name":"GenerateLuchador","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"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":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"generateLuchador","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"imageData","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"uint256","name":"_tokenId","type":"uint256"}],"name":"metadata","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","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":[],"name":"pauseSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_LinkFee","type":"uint256"}],"name":"setLinkFee","outputs":[],"stateMutability":"nonpayable","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":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"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":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c06040527faa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445600f55671bc16d674ec80000601055601180546001600160a01b031990811673f0d54349addcf704f77ae15b96510dea15cb7952179091556012805490911673514910771af9ca656af840dff83e8264ecf986ca1790553480156200008957600080fd5b50601154601254604080518082018252600a808252694c75636861646f72657360b01b6020808401919091528351808501909452908352694c55434841444f52455360b01b908301526001600160a01b03938416939092169190620000f56301ffc9a760e01b62001cca565b81516200010a90600690602085019062001d53565b5080516200012090600790602084019062001d53565b50620001336380ac58cd60e01b62001cca565b62000145635b5e139f60e01b62001cca565b6200015763780e9d6360e01b62001cca565b5050600a805460ff1916905560006200016f62001d4f565b600a8054610100600160a81b0319166101006001600160a01b03841690810291909117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506001600b556001600160601b0319606092831b811660a090815291831b166080908152600e80546001600160a01b031916737a250d5630b4cf539739df2c5dacb4c659f2488d1790556040805161018081018252600661014082018181526565626562663760d01b6101608401528252825180840184528181526518b198b2193360d11b60208281019190915283810191909152835180850185528281526518d8cc190cd960d21b81830152838501528351808501855282815265190c8c998e4d60d21b8183015296830196909652825180840184528181526538393065633160d01b81880152938201939093528151808301835283815265062c66872c8760d31b818701529381019390935280518082018252828152650c4e588d4d4d60d21b8186015260c084015280518082018252828152651899b1b0b19b60d11b8186015260e0840152805180820182528281526566376332336360d01b8186015261010084015280518082019091529081526533189c32993360d11b928101929092526101208101919091526200035f90601390600a62001dd8565b50604080516101808101825260066101408201818152653230b230b29b60d11b610160840152825282518084018452818152651899989a18b360d11b60208281019190915280840191909152835180850185528281526519584c4e0d1960d21b818301528385015283518085018552828152653298199b1cb360d11b81830152606084015283518085018552828152651c9a9898b21960d11b8183015260808401528351808501855282815265191c1a9a329b60d11b8183015260a0840152835180850185528281526531646139353160d01b8183015260c0840152835180850185528281526531316239623560d01b8183015260e0840152835180850185528281526565386236336160d01b8183015261010084015283518085019094529083526565323833323760d01b90830152610120810191909152620004a890601490600a62001dd8565b506040805161018081018252600661014082018181526533623662613560d01b6101608401528252825180840184528181526533623866613560d01b60208281019190915280840191909152835180850185528281526533626135393960d01b8183015283850152835180850185528281526533626135373760d01b818301526060840152835180850185528281526519999c9c1a1960d11b81830152608084015283518085018552828152651bb3309a99b160d11b8183015260a08401528351808501855282815265309a9c1919b160d11b8183015260c08401528351808501855282815265309a9b1c99b160d11b8183015260e084015283518085018552828152650e0d0d198c5960d21b818301526101008401528351808501909452908352651a32991c981b60d11b90830152610120810191909152620005f190601590600a62001dd8565b506040805161018081018252600661014082018181526566396431623760d01b6101608401528252825180840184528181526566376238393760d01b60208281019190915280840191909152835180850185528281526566333963373760d01b81830152838501528351808501855282815265199998d88e0d60d21b818301526060840152835180850185528281526562643765343760d01b8183015260808401528351808501855282815265311c9bb29a3160d11b8183015260a0840152835180850185528281526506239376135360d41b8183015260c084015283518085018552828152650d584ccc8c4d60d21b8183015260e0840152835180850185528281526535303237306560d01b8183015261010084015283518085019094529083526533613162303960d01b908301526101208101919091526200073a90601690600a62001dd8565b50604051806040016040528063109d5b1b60e21b6001600160a01b031916815260200160405180610100016040528060db81526020016200744b60db91399052600080526017602090815281517fd840e16649f6b9a295d95876f4633d3a6b10b55e8162971cf78afd886d5ec89b80546001600160601b03191660a09290921c9190911781558282015180519192620007f9927fd840e16649f6b9a295d95876f4633d3a6b10b55e8162971cf78afd886d5ec89c929091019062001d53565b509050506040518060400160405280652530b3bab0b960d11b6001600160a01b031916815260200160405180610120016040528060f281526020016200735960f29139905260016000526017602090815281517ff36d6bc9642eb6fb6ee9998b09ce990566df752ab06e11f8de7ab633bbd57b8f80546001600160601b03191660a09290921c9190911781558282015180519192620008be927ff36d6bc9642eb6fb6ee9998b09ce990566df752ab06e11f8de7ab633bbd57b90929091019062001d53565b50905050604051806040016040528066436c617373696360c81b6001600160a01b031916815260200160405180610100016040528060c181526020016200772a60c191399052600080526018602090815281517f999d26de3473317ead3eeaf34ca78057f1439db67b6953469c3c96ce9caf6bd780546001600160601b03191660a09290921c919091178155828201518051919262000983927f999d26de3473317ead3eeaf34ca78057f1439db67b6953469c3c96ce9caf6bd8929091019062001d53565b50905050604051806040016040528065121bdbd9195960d21b6001600160a01b031916815260200160405180610100016040528060c181526020016200772a60c19139905260016000526018602090815281517ff3794665d3af9b6fb6f858b70185898134f96768ef31c325d52e04f0ac195a4d80546001600160601b03191660a09290921c919091178155828201518051919262000a48927ff3794665d3af9b6fb6f858b70185898134f96768ef31c325d52e04f0ac195a4e929091019062001d53565b5090505060405180604001604052806414da1a5c9d60da1b6001600160a01b031916815260200160405180610120016040528060e18152602001620070ee60e191399052600080526019602090815281517fd2ac945fcc0096878c763e37d6929b78378c1a2defabde8ba7ee5ed1d6e7a5b280546001600160601b03191660a09290921c919091178155828201518051919262000b0b927fd2ac945fcc0096878c763e37d6929b78378c1a2defabde8ba7ee5ed1d6e7a5b3929091019062001d53565b5090505060405180604001604052806913dc195b8814da1a5c9d60b21b6001600160a01b031916815260200160405180610120016040528060ff81526020016200762b60ff9139905260016000526019602090815281517ffc941c3961fb6541da34150022cddf959da0fb2353866a6bfbd249c2da09291480546001600160601b03191660a09290921c919091178155828201518051919262000bd4927ffc941c3961fb6541da34150022cddf959da0fb2353866a6bfbd249c2da092915929091019062001d53565b5090505060405180604001604052806614da5b99db195d60ca1b6001600160a01b03191681526020016040518060c00160405280608181526020016200790460819139905260026000526019602090815281517f6f678ad17c55bce407239525f4bf7f1fe99197d3eb69bfdd9a0db84a9a11b58180546001600160601b03191660a09290921c919091178155828201518051919262000c99927f6f678ad17c55bce407239525f4bf7f1fe99197d3eb69bfdd9a0db84a9a11b582929091019062001d53565b5090505060405180604001604052806953757370656e6465727360b01b6001600160a01b03191681526020016040518060a001604052806079815260200162007a6160799139905260036000526019602090815281517f3e323a6e0522b016fa22111dfed945f89456f9f44f69eac00209d92607a5b94080546001600160601b03191660a09290921c919091178155828201518051919262000d61927f3e323a6e0522b016fa22111dfed945f89456f9f44f69eac00209d92607a5b941929091019062001d53565b50905050604051806040016040528065476c6f76657360d01b6001600160a01b03191681526020016040518060c00160405280608f815260200162006f34608f9139905260008052601a602090815281517fb75ecc04ed35f89790e98640e901bda41eceff0cb896cf2765fb69768025375080546001600160601b03191660a09290921c919091178155828201518051919262000e24927fb75ecc04ed35f89790e98640e901bda41eceff0cb896cf2765fb697680253751929091019062001d53565b5090505060405180604001604052806a57726973742042616e647360a81b6001600160a01b0319168152602001604051806080016040528060418152602001620072eb6041913990526001600052601a602090815281517ff88cd8d612926ebb404e40725c01084b6e9b3ce0344cde068570342cbd448c6180546001600160601b03191660a09290921c919091178155828201518051919262000eed927ff88cd8d612926ebb404e40725c01084b6e9b3ce0344cde068570342cbd448c62929091019062001d53565b50905050604051806040016040528069149a59da1d0810985b9960b21b6001600160a01b03191681526020016040518060600160405280602d81526020016200732c602d913990526002600052601a602090815281517f4c287b3e2c2cb129ae3ba596d613d760b15affdac7242e12903c37a886ea1c4f80546001600160601b03191660a09290921c919091178155828201518051919262000fb5927f4c287b3e2c2cb129ae3ba596d613d760b15affdac7242e12903c37a886ea1c50929091019062001d53565b509050506040518060400160405280681319599d0810985b9960ba1b6001600160a01b031916815260200160405180606001604052806030815260200162006f046030913990526003600052601a602090815281517f4ac83fca211703e3ddb90093cd219714e5e3715bf0b4fd15b0441390534a24e280546001600160601b03191660a09290921c91909117815582820151805191926200107c927f4ac83fca211703e3ddb90093cd219714e5e3715bf0b4fd15b0441390534a24e3929091019062001d53565b5090505060405180604001604052806841726d2042616e647360b81b6001600160a01b03191681526020016040518060600160405280603f8152602001620075ec603f913990526004600052601a602090815281517f06b28f262ad931a15c9e47271fc159a891b2bcb0da2659cac5bbfed4886cf26e80546001600160601b03191660a09290921c919091178155828201518051919262001143927f06b28f262ad931a15c9e47271fc159a891b2bcb0da2659cac5bbfed4886cf26f929091019062001d53565b50905050604051806040016040528066536c656576657360c81b6001600160a01b03191681526020016040518060c0016040528060818152602001620070046081913990526005600052601a602090815281517f82f07edc09f3a46c1925d02252613a7fcc7be7d03b538b0c268df85f2f13a7ab80546001600160601b03191660a09290921c919091178155828201518051919262001208927f82f07edc09f3a46c1925d02252613a7fcc7be7d03b538b0c268df85f2f13a7ac929091019062001d53565b5090505060405180604001604052806414dc1b1a5d60da1b6001600160a01b03191681526020016040518060600160405280603a8152602001620077eb603a9139905260008052601b602090815281517f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea80546001600160601b03191660a09290921c9190911781558282015180519192620012ca927f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026eb929091019062001d53565b5090505060405180604001604052806443726f737360d81b6001600160a01b03191681526020016040518060600160405280603d8152602001620075af603d913990526001600052601b602090815281517f9fafca4c9c0d5c2cbf85f49fd8ab8212430ce78c2a0cb75b51e0f9c4f9ace00380546001600160601b03191660a09290921c91909117815582820151805191926200138d927f9fafca4c9c0d5c2cbf85f49fd8ab8212430ce78c2a0cb75b51e0f9c4f9ace004929091019062001d53565b5090505060405180604001604052806546696572636560d01b6001600160a01b0319168152602001604051806080016040528060538152602001620079856053913990526002600052601b602090815281517f1dd2f4b94a51cfb409e6e317a497f7cfd9013960a1c723f830c49c05a25f08a580546001600160601b03191660a09290921c919091178155828201518051919262001451927f1dd2f4b94a51cfb409e6e317a497f7cfd9013960a1c723f830c49c05a25f08a6929091019062001d53565b5090505060405180604001604052806614dd1c9a5c195960ca1b6001600160a01b03191681526020016040518060e0016040528060a881526020016200785c60a8913990526003600052601b602090815281517f804a3d0621e73505f5f0c57c922f3e57d6b48e175551184eb12f80d7b4a9c78380546001600160601b03191660a09290921c919091178155828201518051919262001516927f804a3d0621e73505f5f0c57c922f3e57d6b48e175551184eb12f80d7b4a9c784929091019062001d53565b50905050604051806040016040528063109bdb1d60e21b6001600160a01b031916815260200160405180608001604052806057815260200162007b4c6057913990526004600052601b602090815281517fa952f8c0f40734b22d2328e0f7ff57eeffee78885b9cf2147ff941cc37e1c86e80546001600160601b03191660a09290921c9190911781558282015180519192620015d8927fa952f8c0f40734b22d2328e0f7ff57eeffee78885b9cf2147ff941cc37e1c86f929091019062001d53565b5090505060405180604001604052806515da5b99d95960d21b6001600160a01b03191681526020016040518060a001604052806072815260200162007ada6072913990526005600052601b602090815281517fb48400cb19cf39e58355a7c9fd856f9b5b7298c53856a6766c6b39755ccafa7980546001600160601b03191660a09290921c91909117815582820151805191926200169c927fb48400cb19cf39e58355a7c9fd856f9b5b7298c53856a6766c6b39755ccafa7a929091019062001d53565b50905050604051806040016040528066436c617373696360c81b6001600160a01b03191681526020016040518060a0016040528060698152602001620070856069913990526006600052601b602090815281517ff5ddd0b8f160eab91dc4f82b50a485a96cf6ab0bfb38460d73171763afb6d5cf80546001600160601b03191660a09290921c919091178155828201518051919262001761927ff5ddd0b8f160eab91dc4f82b50a485a96cf6ab0bfb38460d73171763afb6d5d0929091019062001d53565b509050506040518060400160405280644172726f7760d81b6001600160a01b03191681526020016040518060c0016040528060898152602001620075266089913990526007600052601b602090815281517f6fa0adbc19babfec7e85ff6417830cdb284ababb3de438515569d7f3d9b3493180546001600160601b03191660a09290921c919091178155828201518051919262001824927f6fa0adbc19babfec7e85ff6417830cdb284ababb3de438515569d7f3d9b34932929091019062001d53565b50905050604051806040016040528063088c2e6d60e31b6001600160a01b03191681526020016040518060e0016040528060a78152602001620071cf60a7913990526008600052601b602090815281517f90dc0d05fc750d51b3e484087edb4e9beb1a58b38bc8386c0e048690482d89ed80546001600160601b03191660a09290921c9190911781558282015180519192620018e6927f90dc0d05fc750d51b3e484087edb4e9beb1a58b38bc8386c0e048690482d89ee929091019062001d53565b509050506040518060400160405280684d6f7573746163686560b81b6001600160a01b031916815260200160405180608001604052806041815260200162007a2060419139905260008052601c602090815281517fb9c6de81004e18dedadca3e5eabaab449ca91dff6f58efc9461da635fe77f84980546001600160601b03191660a09290921c9190911781558282015180519192620019ac927fb9c6de81004e18dedadca3e5eabaab449ca91dff6f58efc9461da635fe77f84a929091019062001d53565b5090505060405180604001604052806554696768747360d01b6001600160a01b03191681526020016040518060600160405280603781526020016200782560379139905260008052601d602090815281517f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd480546001600160601b03191660a09290921c919091178155828201518051919262001a6f927f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd5929091019062001d53565b5090505060405180604001604052806b5472756e6b2054696768747360a01b6001600160a01b03191681526020016040518060a0016040528060758152602001620072766075913990526001600052601d602090815281517f9de6abd965d55c3bb0cdbf6fa175050624c6ff8fe86f682dc08f2a450ede227880546001600160601b03191660a09290921c919091178155828201518051919262001b39927f9de6abd965d55c3bb0cdbf6fa175050624c6ff8fe86f682dc08f2a450ede2279929091019062001d53565b5090505060405180604001604052806754776f20546f6e6560c01b6001600160a01b0319168152602001604051806080016040528060488152602001620079d860489139905260008052601e602090815281517f65ce8396b736f5da9d881cc6fbcb11ef9721292dc41ec8c40879fd9edea5744d80546001600160601b03191660a09290921c919091178155828201518051919262001bfe927f65ce8396b736f5da9d881cc6fbcb11ef9721292dc41ec8c40879fd9edea5744e929091019062001d53565b50905050604051806040016040528063090d2ced60e31b6001600160a01b031916815260200160405180608001604052806041815260200162006fc36041913990526001600052601e602090815281517f873299c6a6c39b8b92f01922bb622df4a3236ea2876aac2da76f6c092cf7e98f80546001600160601b03191660a09290921c919091178155828201518051919262001cc0927f873299c6a6c39b8b92f01922bb622df4a3236ea2876aac2da76f6c092cf7e990929091019062001d53565b5090505062001ebb565b6001600160e01b0319808216141562001d2a576040805162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015290519081900360640190fd5b6001600160e01b0319166000908152602081905260409020805460ff19166001179055565b3390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062001d9657805160ff191683800117855562001dc6565b8280016001018555821562001dc6579182015b8281111562001dc657825182559160200191906001019062001da9565b5062001dd492915062001e38565b5090565b82805482825590600052602060002090810192821562001e2a579160200282015b8281111562001e2a578251805162001e1991849160209091019062001d53565b509160200191906001019062001df9565b5062001dd492915062001e4f565b5b8082111562001dd4576000815560010162001e39565b8082111562001dd457600062001e66828262001e70565b5060010162001e4f565b50805460018160011615610100020316600290046000825580601f1062001e98575062001eb8565b601f01602090049060005260206000209081019062001eb8919062001e38565b50565b60805160601c60a05160601c61501562001eef60003980611a865280613b605250806136645280613b3152506150156000f3fe6080604052600436106101dc5760003560e01c80636352211e11610102578063a22cb46511610095578063cd8ff65711610064578063cd8ff657146107cd578063e3684e39146107f7578063e985e9c514610821578063f2fde38b1461085c576101e3565b8063a22cb46514610680578063b88d4fde146106bb578063bb33d7291461078e578063c87b56dd146107a3576101e3565b8063735de9f7116100d1578063735de9f7146106115780638da5cb5b1461062657806394985ddd1461063b57806395d89b411461066b576101e3565b80636352211e1461058a5780636c0360eb146105b457806370a08231146105c9578063715018a6146105fc576101e3565b80632f745c591161017a57806355367ba91161014957806355367ba91461048a57806355f804b31461049f5780635a0a3a56146105525780635c975abb14610575576101e3565b80632f745c59146103cf5780633ccfd60b1461040857806342842e0e1461041d5780634f6ccce714610460576101e3565b8063081812fc116101b6578063081812fc146102e4578063095ea7b31461032a57806318160ddd1461036557806323b872dd1461038c576101e3565b806301ffc9a7146101e8578063061ba2f11461023057806306fdde03146102cf576101e3565b366101e357005b600080fd5b3480156101f457600080fd5b5061021c6004803603602081101561020b57600080fd5b50356001600160e01b03191661088f565b604080519115158252519081900360200190f35b34801561023c57600080fd5b5061025a6004803603602081101561025357600080fd5b50356108b2565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561029457818101518382015260200161027c565b50505050905090810190601f1680156102c15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102db57600080fd5b5061025a611012565b3480156102f057600080fd5b5061030e6004803603602081101561030757600080fd5b50356110a8565b604080516001600160a01b039092168252519081900360200190f35b34801561033657600080fd5b506103636004803603604081101561034d57600080fd5b506001600160a01b03813516906020013561110a565b005b34801561037157600080fd5b5061037a6111e5565b60408051918252519081900360200190f35b34801561039857600080fd5b50610363600480360360608110156103af57600080fd5b506001600160a01b038135811691602081013590911690604001356111f6565b3480156103db57600080fd5b5061037a600480360360408110156103f257600080fd5b506001600160a01b03813516906020013561124d565b34801561041457600080fd5b50610363611278565b34801561042957600080fd5b506103636004803603606081101561044057600080fd5b506001600160a01b0381358116916020810135909116906040013561136e565b34801561046c57600080fd5b5061037a6004803603602081101561048357600080fd5b5035611389565b34801561049657600080fd5b5061036361139f565b3480156104ab57600080fd5b50610363600480360360208110156104c257600080fd5b8101906020810181356401000000008111156104dd57600080fd5b8201836020820111156104ef57600080fd5b8035906020019184600183028401116401000000008311171561051157600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061140b945050505050565b6103636004803603604081101561056857600080fd5b5080359060200135611476565b34801561058157600080fd5b5061021c6118ac565b34801561059657600080fd5b5061030e600480360360208110156105ad57600080fd5b50356118b5565b3480156105c057600080fd5b5061025a6118dd565b3480156105d557600080fd5b5061037a600480360360208110156105ec57600080fd5b50356001600160a01b031661193e565b34801561060857600080fd5b506103636119a6565b34801561061d57600080fd5b5061030e611a58565b34801561063257600080fd5b5061030e611a67565b34801561064757600080fd5b506103636004803603604081101561065e57600080fd5b5080359060200135611a7b565b34801561067757600080fd5b5061025a611b06565b34801561068c57600080fd5b50610363600480360360408110156106a357600080fd5b506001600160a01b0381351690602001351515611b67565b3480156106c757600080fd5b50610363600480360360808110156106de57600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561071957600080fd5b82018360208201111561072b57600080fd5b8035906020019184600183028401116401000000008311171561074d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611c6c945050505050565b34801561079a57600080fd5b50610363611cca565b3480156107af57600080fd5b5061025a600480360360208110156107c657600080fd5b5035611d34565b3480156107d957600080fd5b50610363600480360360208110156107f057600080fd5b5035611e75565b34801561080357600080fd5b5061025a6004803603602081101561081a57600080fd5b5035611edc565b34801561082d57600080fd5b5061021c6004803603604081101561084457600080fd5b506001600160a01b0381358116916020013516612bb9565b34801561086857600080fd5b506103636004803603602081101561087f57600080fd5b50356001600160a01b0316612be7565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60606108bd82612cf5565b61090e576040805162461bcd60e51b815260206004820152601c60248201527f696d616765446174613a206e6f6e6578697374656e7420746f6b656e00000000604482015290519081900360640190fd5b6000828152601f602052604090205461096e576040805162461bcd60e51b815260206004820181905260248201527f696d616765446174613a20646e61206e6f74207965742067656e657261746564604482015290519081900360640190fd5b610976614518565b6000838152601f602052604090205461098e90612d02565b90506060816001602002015160ff1615806109b05750602082015160ff166001145b6109c957604051806020016040528060008152506109e3565b6040518060c00160405280609d8152602001614eaa609d91395b90506060826001602002015160ff16600114610a0e5760405180602001604052806000815250610a2b565b60405180610180016040528061014c8152602001614c6e61014c91395b9050610a3685612d50565b610a408685612e2b565b845160ff9081166000908152601760209081526040808320828a01518516845260188352818420828b0151861685526019845282852060608c015187168652601a855283862060808d015188168752601b865284872060a08e015189168852601c875285882060c08f01519099168852601d9096529386206001938401979284019691840195948401948c94908101938c939082019290910190601e908f6007602002015160ff1681526020019081526020016000206001016040516020018080701e39bb339034b21e93b63ab1b430b237b960791b8152506011018d805190602001908083835b60208310610b475780518252601f199092019160209182019101610b28565b6001836020036101000a03801982511681845116808217855250505050505090500180614f78603991396039018c805190602001908083835b60208310610b9f5780518252601f199092019160209182019101610b80565b6001836020036101000a038019825116818451168082178552505050505050905001807f3c6720636c6173733d276c756368612d62726561746865273e000000000000008152506019018b805460018160011615610100020316600290048015610c405780601f10610c1e576101008083540402835291820191610c40565b820191906000526020600020905b815481529060010190602001808311610c2c575b50508a805460018160011615610100020316600290048015610c995780601f10610c77576101008083540402835291820191610c99565b820191906000526020600020905b815481529060010190602001808311610c85575b505080614dfd60ad913960ad0189805460018160011615610100020316600290048015610cfd5780601f10610cdb576101008083540402835291820191610cfd565b820191906000526020600020905b815481529060010190602001808311610ce9575b505088805460018160011615610100020316600290048015610d565780601f10610d34576101008083540402835291820191610d56565b820191906000526020600020905b815481529060010190602001808311610d42575b5050875160208901908083835b60208310610d825780518252601f199092019160209182019101610d63565b6001836020036101000a03801982511681845116808217855250505050505090500180614bcc6072913960720180741e339031b630b9b99e93b63ab1b43096b0b63a139f60591b81525060150186805460018160011615610100020316600290048015610e265780601f10610e04576101008083540402835291820191610e26565b820191906000526020600020905b815481529060010190602001808311610e12575b505080631e17b39f60e11b81525060040185805190602001908083835b60208310610e625780518252601f199092019160209182019101610e43565b6001836020036101000a0380198251168184511680821785525050505050509050018061477960de913960de01602f614fb18239602f01603661465b823960360184805460018160011615610100020316600290048015610efa5780601f10610ed8576101008083540402835291820191610efa565b820191906000526020600020905b815481529060010190602001808311610ee6575b5050631e17b39f60e11b8152600401603f6148578239603f0160416148ee823960410183805460018160011615610100020316600290048015610f745780601f10610f52576101008083540402835291820191610f74565b820191906000526020600020905b815481529060010190602001808311610f60575b505080614b0b6049913960490182805460018160011615610100020316600290048015610fd85780601f10610fb6576101008083540402835291820191610fd8565b820191906000526020600020905b815481529060010190602001808311610fc4575b505080651e17b9bb339f60d11b8152506006019c505050505050505050505050506040516020818303038152906040529350505050919050565b60068054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561109e5780601f106110735761010080835404028352916020019161109e565b820191906000526020600020905b81548152906001019060200180831161108157829003601f168201915b5050505050905090565b60006110b382612cf5565b6110ee5760405162461bcd60e51b815260040180806020018281038252602c815260200180614adf602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000611115826118b5565b9050806001600160a01b0316836001600160a01b031614156111685760405162461bcd60e51b8152600401808060200182810382526021815260200180614dba6021913960400191505060405180910390fd5b806001600160a01b031661117a6132f5565b6001600160a01b0316148061119b575061119b816111966132f5565b612bb9565b6111d65760405162461bcd60e51b81526004018080602001828103825260388152602001806149a56038913960400191505060405180910390fd5b6111e083836132f9565b505050565b60006111f16002613367565b905090565b6112076112016132f5565b82613372565b6112425760405162461bcd60e51b8152600401808060200182810382526031815260200180614f476031913960400191505060405180910390fd5b6111e0838383613416565b6001600160a01b038216600090815260016020526040812061126f9083613562565b90505b92915050565b6112806132f5565b6001600160a01b0316611291611a67565b6001600160a01b0316146112da576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b604051600090339047908381818185875af1925050503d806000811461131c576040519150601f19603f3d011682016040523d82523d6000602084013e611321565b606091505b505090508061136b576040805162461bcd60e51b815260206004820152601160248201527015da5d1a191c985dd85b0819985a5b1959607a1b604482015290519081900360640190fd5b50565b6111e083838360405180602001604052806000815250611c6c565b60008061139760028461356e565b509392505050565b6113a76132f5565b6001600160a01b03166113b8611a67565b6001600160a01b031614611401576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b61140961358a565b565b6114136132f5565b6001600160a01b0316611424611a67565b6001600160a01b03161461146d576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b61136b8161362a565b6002600b5414156114ce576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600b556114db6118ac565b15611520576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b61271061152d600d61363d565b1061157f576040805162461bcd60e51b815260206004820152601a60248201527f6d6178696d756d206c75636861646f7265732072656163686564000000000000604482015290519081900360640190fd5b6127108261158d600d61363d565b0111156115e1576040805162461bcd60e51b815260206004820181905260248201527f6d696e74207175616e746974792065786365656473206d617820737570706c79604482015290519081900360640190fd5b6000821180156115f2575060148211155b61162d5760405162461bcd60e51b8152600401808060200182810382526022815260200180614ddb6022913960400191505060405180910390fd5b6010546040805160028082526060808301845293860293926020830190803683375050600e54604080516315ab88c960e31b815290519394506001600160a01b039091169263ad5c464892506004808301926020929190829003018186803b15801561169857600080fd5b505afa1580156116ac573d6000803e3d6000fd5b505050506040513d60208110156116c257600080fd5b5051815182906000906116d157fe5b6001600160a01b0392831660209182029290920101526012548251911690829060019081106116fc57fe5b6001600160a01b03928316602091820292909201810191909152600e5460405163fb3bdb4160e01b815260048101868152306044830181905260648301899052608060248401908152875160848501528751949096169563fb3bdb419534958a958a958d949093909260a490920191878201910280838360005b8381101561178e578181015183820152602001611776565b50505050905001955050505050506000604051808303818588803b1580156117b557600080fd5b505af11580156117c9573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156117f357600080fd5b810190808051604051939291908464010000000082111561181357600080fd5b90830190602082018581111561182857600080fd5b825186602082028301116401000000008211171561184557600080fd5b82525081516020918201928201910280838360005b8381101561187257818101518382015260200161185a565b505050509050016040525050505060005b848110156118a0576118984382900340613641565b600101611883565b50506001600b55505050565b600a5460ff1690565b600061127282604051806060016040528060298152602001614a076029913960029190613781565b60098054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561109e5780601f106110735761010080835404028352916020019161109e565b60006001600160a01b0382166119855760405162461bcd60e51b815260040180806020018281038252602a8152602001806149dd602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061127290613367565b6119ae6132f5565b6001600160a01b03166119bf611a67565b6001600160a01b031614611a08576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b600a5460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600a8054610100600160a81b0319169055565b600e546001600160a01b031681565b600a5461010090046001600160a01b031690565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611af8576040805162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00604482015290519081900360640190fd5b611b02828261378e565b5050565b60078054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561109e5780601f106110735761010080835404028352916020019161109e565b611b6f6132f5565b6001600160a01b0316826001600160a01b03161415611bd5576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000611be26132f5565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155611c266132f5565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b611c7d611c776132f5565b83613372565b611cb85760405162461bcd60e51b8152600401808060200182810382526031815260200180614f476031913960400191505060405180910390fd5b611cc4848484846137ea565b50505050565b611cd26132f5565b6001600160a01b0316611ce3611a67565b6001600160a01b031614611d2c576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b61140961383c565b6060611d3f82612cf5565b611d7a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614b9d602f913960400191505060405180910390fd5b6060611d846118dd565b90506000815111611da45760405180602001604052806000815250611e6e565b80611dae84612d50565b6040516020018083805190602001908083835b60208310611de05780518252601f199092019160209182019101611dc1565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310611e285780518252601f199092019160209182019101611e09565b6001836020036101000a0380198251168184511680821785525050505050509050018064173539b7b760d91b815250600501925050506040516020818303038152906040525b9392505050565b611e7d6132f5565b6001600160a01b0316611e8e611a67565b6001600160a01b031614611ed7576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b601055565b6060611ee782612cf5565b611f38576040805162461bcd60e51b815260206004820152601b60248201527f6d657461646174613a206e6f6e6578697374656e7420746f6b656e0000000000604482015290519081900360640190fd5b6000828152601f6020526040902054611f98576040805162461bcd60e51b815260206004820152601f60248201527f6d657461646174613a20646e61206e6f74207965742067656e65726174656400604482015290519081900360640190fd5b611fa0614518565b6000838152601f6020526040902054611fb890612d02565b9050611fc2614537565b60408051610100808201808452855160ff166000908152601760209081529085902061014085018652805460a01b6001600160a01b0319168352600180820180548851600293821615909702600019011691909104601f8101849004840286018401909752868552949586959394919361012087019390919083018282801561208c5780601f106120615761010080835404028352916020019161208c565b820191906000526020600020905b81548152906001019060200180831161206f57829003601f168201915b50505091909252505050815260208481015160ff1660009081526018825260409081902081518083018352815460a01b6001600160a01b0319168152600180830180548551600261010094831615949094026000190190911692909204601f810187900487028301870190955284825295850195919492938584019391929183018282801561215c5780601f106121315761010080835404028352916020019161215c565b820191906000526020600020905b81548152906001019060200180831161213f57829003601f168201915b50505091909252505050815260408481015160ff166000908152601960209081529082902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f81018690048602830186019096528582529584019591949293858101939192919083018282801561222e5780601f106122035761010080835404028352916020019161222e565b820191906000526020600020905b81548152906001019060200180831161221157829003601f168201915b505050919092525050508152606084015160ff166000908152601a602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252958401959194929385810193919291908301828280156123015780601f106122d657610100808354040283529160200191612301565b820191906000526020600020905b8154815290600101906020018083116122e457829003601f168201915b505050919092525050508152608084015160ff166000908152601b602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252958401959194929385810193919291908301828280156123d45780601f106123a9576101008083540402835291602001916123d4565b820191906000526020600020905b8154815290600101906020018083116123b757829003601f168201915b50505091909252505050815260a08481015160ff166000908152601c602090815260409182902082518084018452815490941b6001600160a01b0319168452600180820180548551600261010094831615949094026000190190911692909204601f8101859004850283018501909552848252958301959193858401939192918301828280156124a55780601f1061247a576101008083540402835291602001916124a5565b820191906000526020600020905b81548152906001019060200180831161248857829003601f168201915b50505091909252505050815260c084015160ff166000908152601d602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252958401959194929385810193919291908301828280156125785780601f1061254d57610100808354040283529160200191612578565b820191906000526020600020905b81548152906001019060200180831161255b57829003601f168201915b50505091909252505050815260e084015160ff166000908152601e602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f81018690048602830186019096528582529584019591949293858101939192919083018282801561264b5780601f106126205761010080835404028352916020019161264b565b820191906000526020600020905b81548152906001019060200180831161262e57829003601f168201915b50505050508152505081525090506060612663614565565b506040805161014081018252600661010082019081526514dc1a5c9a5d60d21b6101208301528152815180830183526004808252634361706560e01b6020838101919091528084019290925283518085018552600580825264546f72736f60d81b8285015284860191909152845180860186528281526341726d7360e01b81850152606085015284518086018652918252634d61736b60e01b828401526080840191909152835180850185528181526409adeeae8d60db1b8184015260a0840152835180850185526007815266426f74746f6d7360c81b8184015260c08401528351808501909452835264426f6f747360d81b9083015260e081019190915260005b60088110156129a15783816008811061277a57fe5b6020020151516001600160a01b03191661279357612999565b8283516000146127be57604051806040016040528060038152602001622c207b60e81b8152506127d9565b604051806040016040528060018152602001607b60f81b8152505b8383600881106127e557fe5b60200201516128048785600881106127f957fe5b6020020151516138bf565b6040516020018085805190602001908083835b602083106128365780518252601f199092019160209182019101612817565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b6020831061287e5780518252601f19909201916020918201910161285f565b51815160209384036101000a60001901801990921691161790526e113a3930b4ba2fba3cb832911d101160891b919093019081528551600f90910192860191508083835b602083106128e15780518252601f1990920191602091820191016128c2565b51815160209384036101000a600019018019909216911617905261088b60f21b9190930190815269113b30b63ab2911d101160b11b60028201528451600c90910192850191508083835b6020831061294a5780518252601f19909201916020918201910161292b565b5181516020939093036101000a6000190180199091169216919091179052601160f91b920191825250607d60f81b600182015260408051808303601d1901815260029092019052975050505050505b600101612765565b506129ab86612d50565b6129b4876108b2565b6129bd88612d50565b604051607b60f81b602080830191825272226e616d65223a20224c75636861646f72202360681b602184015285518893603401918701908083835b60208310612a175780518252601f1990920191602091820191016129f8565b5181516020939093036101000a600019018019909116921691909117905261088b60f21b920191825250600201608d614a528239608d01806e1134b6b0b3b2afb230ba30911d101160891b815250600f0184805190602001908083835b60208310612a935780518252601f199092019160209182019101612a74565b5181516020939093036101000a600019018019909116921691909117905261088b60f21b9201918252506002016030614c3e823960300183805190602001908083835b60208310612af55780518252601f199092019160209182019101612ad6565b51815160209384036101000a600019018019909216911617905261088b60f21b919093019081526e2261747472696275746573223a205b60881b60028201528451601190910192850191508083835b60208310612b635780518252601f199092019160209182019101612b44565b5181516020939093036101000a6000190180199091169216919091179052605d60f81b920191825250607d60f81b600182015260408051808303601d19018152600290920190529b9a5050505050505050505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b612bef6132f5565b6001600160a01b0316612c00611a67565b6001600160a01b031614612c49576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b6001600160a01b038116612c8e5760405162461bcd60e51b81526004018080602001828103825260268152602001806148c86026913960400191505060405180910390fd5b600a546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600a80546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60006112726002836139c5565b612d0a614518565b612d12614518565b60005b600c811015612d4957600a84068282600c8110612d2e57fe5b60ff9092166020929092020152600a84049350600101612d15565b5092915050565b606081612d7557506040805180820190915260018152600360fc1b60208201526108ad565b8160005b8115612d8d57600101600a82049150612d79565b60608167ffffffffffffffff81118015612da657600080fd5b506040519080825280601f01601f191660200182016040528015612dd1576020820181803683370190505b50859350905060001982015b8315612e2257600a840660300160f81b82828060019003935081518110612e0057fe5b60200101906001600160f81b031916908160001a905350600a84049350612ddd565b50949350505050565b6060612e3683612d50565b6013836008602002015160ff1681548110612e4d57fe5b90600052602060002001612e6085612d50565b6014856009602002015160ff1681548110612e7757fe5b90600052602060002001612e8a87612d50565b601587600a602002015160ff1681548110612ea157fe5b90600052602060002001612eb489612d50565b601689600b602002015160ff1681548110612ecb57fe5b90600052602060002001612ede8b612d50565b60405160200180806f1e39ba3cb6329f11b63ab1b430b237b960811b8152506010018a805190602001908083835b60208310612f2b5780518252601f199092019160209182019101612f0c565b6001836020036101000a0380198251168184511680821785525050505050509050018075202e6c756368612d62617365207b2066696c6c3a202360501b81525060160189805460018160011615610100020316600290048015612fc55780601f10612fa3576101008083540402835291820191612fc5565b820191906000526020600020905b815481529060010190602001808311612fb1575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0188805190602001908083835b6020831061300a5780518252601f199092019160209182019101612feb565b6001836020036101000a0380198251168184511680821785525050505050509050018074202e6c756368612d616c74207b2066696c6c3a202360581b815250601501878054600181600116156101000203166002900480156130a35780601f106130815761010080835404028352918201916130a3565b820191906000526020600020905b81548152906001019060200180831161308f575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0186805190602001908083835b602083106130e85780518252601f1990920191602091820191016130c9565b6001836020036101000a0380198251168184511680821785525050505050509050018075202e6c756368612d65796573207b2066696c6c3a202360501b815250601601858054600181600116156101000203166002900480156131825780601f10613160576101008083540402835291820191613182565b820191906000526020600020905b81548152906001019060200180831161316e575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0184805190602001908083835b602083106131c75780518252601f1990920191602091820191016131a8565b6001836020036101000a0380198251168184511680821785525050505050509050018075202e6c756368612d736b696e207b2066696c6c3a202360501b815250601601838054600181600116156101000203166002900480156132615780601f1061323f576101008083540402835291820191613261565b820191906000526020600020905b81548152906001019060200180831161324d575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0182805190602001908083835b602083106132a65780518252601f199092019160209182019101613287565b6001836020036101000a038019825116818451168082178552505050505050905001806146bc60bd913960bd019950505050505050505050604051602081830303815290604052905092915050565b3390565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061332e826118b5565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006112728261363d565b600061337d82612cf5565b6133b85760405162461bcd60e51b815260040180806020018281038252602c815260200180614979602c913960400191505060405180910390fd5b60006133c3836118b5565b9050806001600160a01b0316846001600160a01b031614806133fe5750836001600160a01b03166133f3846110a8565b6001600160a01b0316145b8061340e575061340e8185612bb9565b949350505050565b826001600160a01b0316613429826118b5565b6001600160a01b03161461346e5760405162461bcd60e51b8152600401808060200182810382526029815260200180614b746029913960400191505060405180910390fd5b6001600160a01b0382166134b35760405162461bcd60e51b815260040180806020018281038252602481526020018061492f6024913960400191505060405180910390fd5b6134be8383836139d1565b6134c96000826132f9565b6001600160a01b03831660009081526001602052604090206134eb9082613a20565b506001600160a01b038216600090815260016020526040902061350e9082613a2c565b5061351b60028284613a38565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061126f8383613a4e565b600080808061357d8686613ab2565b9097909650945050505050565b6135926118ac565b156135d7576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b600a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861360d6132f5565b604080516001600160a01b039092168252519081900360200190a1565b8051611b0290600990602084019061458d565b5490565b601054604080516370a0823160e01b815230600482015290516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916370a08231916024808301926020929190829003018186803b1580156136aa57600080fd5b505afa1580156136be573d6000803e3d6000fd5b505050506040513d60208110156136d457600080fd5b50511015613729576040805162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e747261637400604482015290519081900360640190fd5b600061373a600f5460105484613b2d565b9050613746600d613ce0565b604051806020016040528061375b600d61363d565b90526000828152602080526040902090519055611b023361377c600d61363d565b613ce9565b600061340e848484613d03565b60008281526020808052604080832080548452601f83528184208590559285905281805291548251848152925190927f1d584699e20b45cf7fb70771dbd92bb407c244dd750faf0d3c3108aaae7d0e7292908290030190a25050565b6137f5848484613416565b61380184848484613dcd565b611cc45760405162461bcd60e51b81526004018080602001828103825260328152602001806148966032913960400191505060405180910390fd5b6138446118ac565b61388c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b600a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61360d6132f5565b606060005b600c8160ff161080156138f25750828160ff16600c81106138e157fe5b1a60f81b6001600160f81b03191615155b156138ff576001016138c4565b60608160ff1667ffffffffffffffff8111801561391b57600080fd5b506040519080825280601f01601f191660200182016040528015613946576020820181803683370190505b509050600091505b600c8260ff1610801561397c5750838260ff16600c811061396b57fe5b1a60f81b6001600160f81b03191615155b15611e6e57838260ff16600c811061399057fe5b1a60f81b818360ff16815181106139a357fe5b60200101906001600160f81b031916908160001a90535060019091019061394e565b600061126f8383613f35565b6139dc8383836111e0565b6139e46118ac565b156111e05760405162461bcd60e51b815260040180806020018281038252602b815260200180614691602b913960400191505060405180910390fd5b600061126f8383613f4d565b600061126f8383614013565b600061340e84846001600160a01b03851661405d565b81546000908210613a905760405162461bcd60e51b81526004018080602001828103825260228152602001806146396022913960400191505060405180910390fd5b826000018281548110613a9f57fe5b9060005260206000200154905092915050565b815460009081908310613af65760405162461bcd60e51b8152600401808060200182810382526022815260200180614a306022913960400191505060405180910390fd5b6000846000018481548110613b0757fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634000aea07f000000000000000000000000000000000000000000000000000000000000000085878660405160200180838152602001828152602001925050506040516020818303038152906040526040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613c09578181015183820152602001613bf1565b50505050905090810190601f168015613c365780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015613c5757600080fd5b505af1158015613c6b573d6000803e3d6000fd5b505050506040513d6020811015613c8157600080fd5b50506000848152600c6020526040812054613ca1908690859030906140f4565b6000868152600c6020526040902054909150613cbe90600161413b565b6000868152600c6020526040902055613cd78582614195565b95945050505050565b80546001019055565b611b028282604051806020016040528060008152506141c1565b60008281526001840160205260408120548281613d9e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613d63578181015183820152602001613d4b565b50505050905090810190601f168015613d905780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50846000016001820381548110613db157fe5b9060005260206000209060020201600101549150509392505050565b6000613de1846001600160a01b0316614213565b613ded5750600161340e565b6060613efb630a85bd0160e11b613e026132f5565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613e69578181015183820152602001613e51565b50505050905090810190601f168015613e965780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001614896603291396001600160a01b0388169190614219565b90506000818060200190516020811015613f1457600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156140095783546000198083019190810190600090879083908110613f8057fe5b9060005260206000200154905080876000018481548110613f9d57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080613fcd57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050611272565b6000915050611272565b600061401f8383613f35565b61405557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611272565b506000611272565b6000828152600184016020526040812054806140c2575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611e6e565b828560000160018303815481106140d557fe5b9060005260206000209060020201600101819055506000915050611e6e565b60408051602080820196909652808201949094526001600160a01b039290921660608401526080808401919091528151808403909101815260a09092019052805191012090565b60008282018381101561126f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6141cb8383614228565b6141d86000848484613dcd565b6111e05760405162461bcd60e51b81526004018080602001828103825260328152602001806148966032913960400191505060405180910390fd5b3b151590565b606061340e8484600085614356565b6001600160a01b038216614283576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b61428c81612cf5565b156142de576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b6142ea600083836139d1565b6001600160a01b038216600090815260016020526040902061430c9082613a2c565b5061431960028284613a38565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060824710156143975760405162461bcd60e51b81526004018080602001828103825260268152602001806149536026913960400191505060405180910390fd5b6143a085614213565b6143f1576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106144305780518252601f199092019160209182019101614411565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614492576040519150601f19603f3d011682016040523d82523d6000602084013e614497565b606091505b50915091506144a78282866144b2565b979650505050505050565b606083156144c1575081611e6e565b8251156144d15782518084602001fd5b60405162461bcd60e51b8152602060048201818152845160248401528451859391928392604401919085019080838360008315613d63578181015183820152602001613d4b565b604051806101800160405280600c906020820280368337509192915050565b6040518061010001604052806008905b61454f61460b565b8152602001906001900390816145475790505090565b6040518061010001604052806008905b60608152602001906001900390816145755790505090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106145ce57805160ff19168380011785556145fb565b828001600101855582156145fb579182015b828111156145fb5782518255916020019190600101906145e0565b50614607929150614623565b5090565b60408051808201909152600081526060602082015290565b5b80821115614607576000815560010161462456fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64733c706174682066696c6c3d272330303027206f7061636974793d272e392720643d274d3133203131682d3376316834762d317a272f3e4552433732315061757361626c653a20746f6b656e207472616e73666572207768696c6520706175736564202e6c756368612d62726561746865207b20616e696d6174696f6e3a20302e3573206c756368612d6272656174686520696e66696e69746520616c7465726e61746520656173652d696e2d6f75743b207d20406b65796672616d6573206c756368612d62726561746865207b2066726f6d207b207472616e73666f726d3a207472616e736c6174655928307078293b207d20746f207b207472616e73666f726d3a207472616e736c61746559283125293b207d207d3c2f7374796c653e3c706174682066696c6c3d27234646462720643d274d39203648367633683456367a4d31372036682d337633683456367a272f3e3c7061746820636c6173733d276c756368612d657965732720643d274d31362036682d327633683356367a4d382036483776336833563648397a272f3e3c706174682066696c6c3d27234646462720643d274d3720366831763148377a4d3136203668317631682d317a27206f7061636974793d272e34272f3e3c706174682066696c6c3d27233030302720643d274d3135203768317631682d317a4d3820376831763148387a272f3e3c7061746820636c6173733d276c756368612d736b696e2720643d274d3136203233762d3648387636483776316834762d34683276346834762d317a272f3e4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573733c7061746820636c6173733d276c756368612d626173652720643d274d31352031374838763168317631683276316832762d316832762d316831762d317a272f3e4552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e6473226465736372697074696f6e223a20224c75636861646f726573206172652072616e646f6d6c792067656e657261746564207573696e6720436861696e6c696e6b2056524620616e6420686176652031303025206f6e2d636861696e2061727420616e64206d65746164617461202d204f6e6c792031303030302077696c6c206576657220657869737421222c4552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e3c7061746820636c6173733d276c756368612d626173652720643d274d3920323148387632483776316834762d33682d317a4d3136203233762d32682d3376336834762d317a272f3e4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e3c7061746820636c6173733d276c756368612d626173652720643d274d313820355633682d315632682d315631682d3156304839763148387631483776314836763248357635683176326831763168317631683176316836762d316831762d316831762d316831762d32683156357a272f3e2265787465726e616c5f75726c223a202268747470733a2f2f6c75636861646f7265732e696f2f6c75636861646f722f3c7061746820636c6173733d276c756368612d616c742720643d274d313820345633682d315632682d315631682d3156304839763148387631483776314836763248357635683156366831563568325634683156336834763168317631683276316831763468315635682d317a272f3e3c672066696c6c3d2723303030273e3c7061746820643d274d313820345633682d315632682d315631682d3156304839763148387631483776314836763248357635683156356831563468315633683156326836763168317631683176316831763568315635682d317a27206f7061636974793d272e32272f3e3c7061746820643d274d313620345633682d31563248397631483876314837763168325634683156336834763168317631683256347a4d3620356831763148367a4d3137203568317631682d317a27206f7061636974793d272e35272f3e3c2f673e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65726d696e74207175616e74697479206d757374206265206265747765656e20312d32303c7061746820636c6173733d276c756368612d736b696e2720643d274d3232203132762d31682d31762d31682d315639682d315635682d315633682d315632682d315631682d3156304839763148387631483776314836763248357634483476314833763148327631483176386834762d316831762d324835762d336831763168317631683176326838762d326831762d316831762d3168317633682d317632683176316834762d387a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d32302031305639682d327631682d3176316834762d317a4d35203948347631483376316834762d31483656397a272f3e3c706174682066696c6c3d272330303027206f7061636974793d272e322720643d274d36203948347631483376316834762d3148367a4d32302031305639682d327631682d3176316834762d317a272f3e4552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665642720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f737667272076696577426f783d27302030203234203234273e3c7061746820636c6173733d276c756368612d736b696e2720643d274d3134203130483976336836762d337a272f3ea2646970667358221220f07ff78f47503188bddd1cb2cc6410513aab09c35bef87db8e84d77cf54338e964736f6c634300060c00333c7061746820636c6173733d276c756368612d626173652720643d274d3232203134682d3376316834762d317a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d35203136483176336834762d316831762d3148357a4d3232203136682d337631682d317631683176316834762d337a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d33203136483176316834762d3148347a4d3232203136682d3376316834762d317a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d39203230483876316833762d31682d317a4d3135203230682d3276316833762d317a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d3232203134682d3376336834762d337a4d33203134483176336834762d3348347a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d3232203134682d3376316834762d317a4d33203134483176316834762d3148347a272f3e3c7061746820643d274d313820355633682d315632682d317632682d317631682d317631682d317633682d325636682d31563548395634483856324837763148367632483576346831763168327633683176316836762d316831762d3368325639683156357a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d3232203132762d31682d31762d31682d315639483476314833763148327631483176356834762d336831763168317631683176326838762d326831762d316831762d31683176336834762d357a272f3e3c7061746820643d274d3232203132762d31682d31762d31682d315639483476314833763148327631483176356834762d336831763168317631683176326838762d326831762d316831762d31683176336834762d357a272066696c6c3d272330303027206f7061636974793d272e3135272f3e3c7061746820643d274d313320335632682d32763268327a4d313320315630682d32763168317a4d313020344839563148387631483776314836763248357635683176326831763168317631683176316831762d324839762d3368325635682d317a4d313820355633682d315632682d315631682d317633682d317631682d31763568327633682d3176326831762d316831762d316831762d316831762d32683156357a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d3135203137483876336838762d337a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d31352031387631682d3276346833762d357a4d39203139762d31483876356833762d34682d317a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d33203135483176326834762d3248347a4d3232203135682d3376326834762d327a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d34203134483176316834762d317a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d36203256314835763568315635683156336831563248377a4d313820317631682d3276316831763268317631683156317a272f3e3c672066696c6c3d2723303030273e3c7061746820643d274d3520316831763148357a4d36203276316832563248377a4d3138203168317631682d317a4d31362032763168325632682d317a27206f7061636974793d272e33272f3e3c7061746820643d274d36203356324835763468315635683156337a4d313820327631682d31763268317631683156327a27206f7061636974793d272e32272f3e3c2f673e3c706174682066696c6c3d27234139413138412720643d274d323120325631682d315630682d31763268317631682d3376326832763168325635683156327a4d352033483456326831563048347631483376314832763368317631683256356832563348367a272f3e3c672066696c6c3d272330303027206f7061636974793d272e3135273e3c7061746820643d274d3231203468317631682d317a4d31392035682d31763168335635682d317a272f3e3c7061746820643d274d3220346831763148327a4d342035483376316833563548357a272f3e3c2f673e3c7061746820643d274d313820355633682d315632682d315631682d3156304839763148387631483776314836763248357635683176326831763168317631683176316831762d3468315635483956336831563268315631683276316831763168317632682d327636683176346831762d316831762d316831762d316831762d32683156357a272f3e3c7061746820643d274d31342032682d315630682d327632483976326832763468325634683256327a4d3132203133682d3176326832762d327a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d34203134483176316834762d317a4d3232203134682d3376316834762d317a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d31302039483476314833763148327631483176336834762d31683176316831763168317632683356397a4d3232203132762d31682d31762d31682d315639682d3776396833762d326831762d316831762d31683176316834762d337a272f3e3c7061746820643d274d31302039483476314833763148327631483176336834762d31683176316831763168317632683356397a4d3232203132762d31682d31762d31682d315639682d3776396833762d326831762d316831762d31683176316834762d337a272066696c6c3d272330303027206f7061636974793d272e3135272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d323020313148337631326831762d316832762d3168313276316832763168315631317a272f3e3c672066696c6c3d2723303030273e3c70617468206f7061636974793d272e322720643d274d323020313176313268315631317a4d33203132763131683156313148337a272f3e3c70617468206f7061636974793d272e352720643d274d313920313148347631316832762d31683132763168325631317a272f3e3c2f673e3c7061746820643d274d31312030483976314838763148377631483676324835763568317632683176316831763168317631683356307a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d3135203137483876366833762d33683276336833762d367a272f3e3c7061746820643d274d313120326832563168315630682d34763168317a4d3620313076326831762d316831762d3148377a4d3137203130682d317631683176316831762d327a272f3e3c7061746820643d274d3136203368315632682d315631682d317631682d317631682d317631682d325633682d3156324839563148387631483776316831763168317631683176316831763968325636683156356831563468317a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d313620394837763368312d317634683176316838762d316831762d34682d31203156397a272f3e3c706174682066696c6c3d272330303027206f7061636974793d272e31352720643d274d3136203948377637683176316838762d31683156397a272f3e3c7061746820643d274d313720337631682d327631682d317631682d317633683556337a4d313120385636682d31563548395634483756334836763668357a4d313120313376326832762d32682d317a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d3920323248387631483776316834762d32682d317a4d3136203233762d31682d3376326834762d317a272f3e3c706174682066696c6c3d272334323163303327206f7061636974793d272e392720643d274d3134203130483976336831762d32683476326831762d337a272f3e3c7061746820636c6173733d276c756368612d626173652720643d274d313520397639683156397a4d3820313076386831563948387a272f3e3c7061746820643d274d3820313076386831563948387a4d313520397639683156397a272066696c6c3d272330303027206f7061636974793d272e3135272f3e3c7061746820643d274d313820355633682d315632682d317631682d317631682d317631682d317631682d325635682d3156344839563348385632483776314836763248357635683176326831762d316831762d31683356396832763168337631683176316831762d32683156357a272f3e3c7061746820643d274d31332033682d335632683156316831563048397631483876314837763148367632683376314838763248377632683156396831563868315637683156366831563568315634683156337a272f3e
Deployed Bytecode
0x6080604052600436106101dc5760003560e01c80636352211e11610102578063a22cb46511610095578063cd8ff65711610064578063cd8ff657146107cd578063e3684e39146107f7578063e985e9c514610821578063f2fde38b1461085c576101e3565b8063a22cb46514610680578063b88d4fde146106bb578063bb33d7291461078e578063c87b56dd146107a3576101e3565b8063735de9f7116100d1578063735de9f7146106115780638da5cb5b1461062657806394985ddd1461063b57806395d89b411461066b576101e3565b80636352211e1461058a5780636c0360eb146105b457806370a08231146105c9578063715018a6146105fc576101e3565b80632f745c591161017a57806355367ba91161014957806355367ba91461048a57806355f804b31461049f5780635a0a3a56146105525780635c975abb14610575576101e3565b80632f745c59146103cf5780633ccfd60b1461040857806342842e0e1461041d5780634f6ccce714610460576101e3565b8063081812fc116101b6578063081812fc146102e4578063095ea7b31461032a57806318160ddd1461036557806323b872dd1461038c576101e3565b806301ffc9a7146101e8578063061ba2f11461023057806306fdde03146102cf576101e3565b366101e357005b600080fd5b3480156101f457600080fd5b5061021c6004803603602081101561020b57600080fd5b50356001600160e01b03191661088f565b604080519115158252519081900360200190f35b34801561023c57600080fd5b5061025a6004803603602081101561025357600080fd5b50356108b2565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561029457818101518382015260200161027c565b50505050905090810190601f1680156102c15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102db57600080fd5b5061025a611012565b3480156102f057600080fd5b5061030e6004803603602081101561030757600080fd5b50356110a8565b604080516001600160a01b039092168252519081900360200190f35b34801561033657600080fd5b506103636004803603604081101561034d57600080fd5b506001600160a01b03813516906020013561110a565b005b34801561037157600080fd5b5061037a6111e5565b60408051918252519081900360200190f35b34801561039857600080fd5b50610363600480360360608110156103af57600080fd5b506001600160a01b038135811691602081013590911690604001356111f6565b3480156103db57600080fd5b5061037a600480360360408110156103f257600080fd5b506001600160a01b03813516906020013561124d565b34801561041457600080fd5b50610363611278565b34801561042957600080fd5b506103636004803603606081101561044057600080fd5b506001600160a01b0381358116916020810135909116906040013561136e565b34801561046c57600080fd5b5061037a6004803603602081101561048357600080fd5b5035611389565b34801561049657600080fd5b5061036361139f565b3480156104ab57600080fd5b50610363600480360360208110156104c257600080fd5b8101906020810181356401000000008111156104dd57600080fd5b8201836020820111156104ef57600080fd5b8035906020019184600183028401116401000000008311171561051157600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061140b945050505050565b6103636004803603604081101561056857600080fd5b5080359060200135611476565b34801561058157600080fd5b5061021c6118ac565b34801561059657600080fd5b5061030e600480360360208110156105ad57600080fd5b50356118b5565b3480156105c057600080fd5b5061025a6118dd565b3480156105d557600080fd5b5061037a600480360360208110156105ec57600080fd5b50356001600160a01b031661193e565b34801561060857600080fd5b506103636119a6565b34801561061d57600080fd5b5061030e611a58565b34801561063257600080fd5b5061030e611a67565b34801561064757600080fd5b506103636004803603604081101561065e57600080fd5b5080359060200135611a7b565b34801561067757600080fd5b5061025a611b06565b34801561068c57600080fd5b50610363600480360360408110156106a357600080fd5b506001600160a01b0381351690602001351515611b67565b3480156106c757600080fd5b50610363600480360360808110156106de57600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561071957600080fd5b82018360208201111561072b57600080fd5b8035906020019184600183028401116401000000008311171561074d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611c6c945050505050565b34801561079a57600080fd5b50610363611cca565b3480156107af57600080fd5b5061025a600480360360208110156107c657600080fd5b5035611d34565b3480156107d957600080fd5b50610363600480360360208110156107f057600080fd5b5035611e75565b34801561080357600080fd5b5061025a6004803603602081101561081a57600080fd5b5035611edc565b34801561082d57600080fd5b5061021c6004803603604081101561084457600080fd5b506001600160a01b0381358116916020013516612bb9565b34801561086857600080fd5b506103636004803603602081101561087f57600080fd5b50356001600160a01b0316612be7565b6001600160e01b0319811660009081526020819052604090205460ff165b919050565b60606108bd82612cf5565b61090e576040805162461bcd60e51b815260206004820152601c60248201527f696d616765446174613a206e6f6e6578697374656e7420746f6b656e00000000604482015290519081900360640190fd5b6000828152601f602052604090205461096e576040805162461bcd60e51b815260206004820181905260248201527f696d616765446174613a20646e61206e6f74207965742067656e657261746564604482015290519081900360640190fd5b610976614518565b6000838152601f602052604090205461098e90612d02565b90506060816001602002015160ff1615806109b05750602082015160ff166001145b6109c957604051806020016040528060008152506109e3565b6040518060c00160405280609d8152602001614eaa609d91395b90506060826001602002015160ff16600114610a0e5760405180602001604052806000815250610a2b565b60405180610180016040528061014c8152602001614c6e61014c91395b9050610a3685612d50565b610a408685612e2b565b845160ff9081166000908152601760209081526040808320828a01518516845260188352818420828b0151861685526019845282852060608c015187168652601a855283862060808d015188168752601b865284872060a08e015189168852601c875285882060c08f01519099168852601d9096529386206001938401979284019691840195948401948c94908101938c939082019290910190601e908f6007602002015160ff1681526020019081526020016000206001016040516020018080701e39bb339034b21e93b63ab1b430b237b960791b8152506011018d805190602001908083835b60208310610b475780518252601f199092019160209182019101610b28565b6001836020036101000a03801982511681845116808217855250505050505090500180614f78603991396039018c805190602001908083835b60208310610b9f5780518252601f199092019160209182019101610b80565b6001836020036101000a038019825116818451168082178552505050505050905001807f3c6720636c6173733d276c756368612d62726561746865273e000000000000008152506019018b805460018160011615610100020316600290048015610c405780601f10610c1e576101008083540402835291820191610c40565b820191906000526020600020905b815481529060010190602001808311610c2c575b50508a805460018160011615610100020316600290048015610c995780601f10610c77576101008083540402835291820191610c99565b820191906000526020600020905b815481529060010190602001808311610c85575b505080614dfd60ad913960ad0189805460018160011615610100020316600290048015610cfd5780601f10610cdb576101008083540402835291820191610cfd565b820191906000526020600020905b815481529060010190602001808311610ce9575b505088805460018160011615610100020316600290048015610d565780601f10610d34576101008083540402835291820191610d56565b820191906000526020600020905b815481529060010190602001808311610d42575b5050875160208901908083835b60208310610d825780518252601f199092019160209182019101610d63565b6001836020036101000a03801982511681845116808217855250505050505090500180614bcc6072913960720180741e339031b630b9b99e93b63ab1b43096b0b63a139f60591b81525060150186805460018160011615610100020316600290048015610e265780601f10610e04576101008083540402835291820191610e26565b820191906000526020600020905b815481529060010190602001808311610e12575b505080631e17b39f60e11b81525060040185805190602001908083835b60208310610e625780518252601f199092019160209182019101610e43565b6001836020036101000a0380198251168184511680821785525050505050509050018061477960de913960de01602f614fb18239602f01603661465b823960360184805460018160011615610100020316600290048015610efa5780601f10610ed8576101008083540402835291820191610efa565b820191906000526020600020905b815481529060010190602001808311610ee6575b5050631e17b39f60e11b8152600401603f6148578239603f0160416148ee823960410183805460018160011615610100020316600290048015610f745780601f10610f52576101008083540402835291820191610f74565b820191906000526020600020905b815481529060010190602001808311610f60575b505080614b0b6049913960490182805460018160011615610100020316600290048015610fd85780601f10610fb6576101008083540402835291820191610fd8565b820191906000526020600020905b815481529060010190602001808311610fc4575b505080651e17b9bb339f60d11b8152506006019c505050505050505050505050506040516020818303038152906040529350505050919050565b60068054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561109e5780601f106110735761010080835404028352916020019161109e565b820191906000526020600020905b81548152906001019060200180831161108157829003601f168201915b5050505050905090565b60006110b382612cf5565b6110ee5760405162461bcd60e51b815260040180806020018281038252602c815260200180614adf602c913960400191505060405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000611115826118b5565b9050806001600160a01b0316836001600160a01b031614156111685760405162461bcd60e51b8152600401808060200182810382526021815260200180614dba6021913960400191505060405180910390fd5b806001600160a01b031661117a6132f5565b6001600160a01b0316148061119b575061119b816111966132f5565b612bb9565b6111d65760405162461bcd60e51b81526004018080602001828103825260388152602001806149a56038913960400191505060405180910390fd5b6111e083836132f9565b505050565b60006111f16002613367565b905090565b6112076112016132f5565b82613372565b6112425760405162461bcd60e51b8152600401808060200182810382526031815260200180614f476031913960400191505060405180910390fd5b6111e0838383613416565b6001600160a01b038216600090815260016020526040812061126f9083613562565b90505b92915050565b6112806132f5565b6001600160a01b0316611291611a67565b6001600160a01b0316146112da576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b604051600090339047908381818185875af1925050503d806000811461131c576040519150601f19603f3d011682016040523d82523d6000602084013e611321565b606091505b505090508061136b576040805162461bcd60e51b815260206004820152601160248201527015da5d1a191c985dd85b0819985a5b1959607a1b604482015290519081900360640190fd5b50565b6111e083838360405180602001604052806000815250611c6c565b60008061139760028461356e565b509392505050565b6113a76132f5565b6001600160a01b03166113b8611a67565b6001600160a01b031614611401576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b61140961358a565b565b6114136132f5565b6001600160a01b0316611424611a67565b6001600160a01b03161461146d576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b61136b8161362a565b6002600b5414156114ce576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b6002600b556114db6118ac565b15611520576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b61271061152d600d61363d565b1061157f576040805162461bcd60e51b815260206004820152601a60248201527f6d6178696d756d206c75636861646f7265732072656163686564000000000000604482015290519081900360640190fd5b6127108261158d600d61363d565b0111156115e1576040805162461bcd60e51b815260206004820181905260248201527f6d696e74207175616e746974792065786365656473206d617820737570706c79604482015290519081900360640190fd5b6000821180156115f2575060148211155b61162d5760405162461bcd60e51b8152600401808060200182810382526022815260200180614ddb6022913960400191505060405180910390fd5b6010546040805160028082526060808301845293860293926020830190803683375050600e54604080516315ab88c960e31b815290519394506001600160a01b039091169263ad5c464892506004808301926020929190829003018186803b15801561169857600080fd5b505afa1580156116ac573d6000803e3d6000fd5b505050506040513d60208110156116c257600080fd5b5051815182906000906116d157fe5b6001600160a01b0392831660209182029290920101526012548251911690829060019081106116fc57fe5b6001600160a01b03928316602091820292909201810191909152600e5460405163fb3bdb4160e01b815260048101868152306044830181905260648301899052608060248401908152875160848501528751949096169563fb3bdb419534958a958a958d949093909260a490920191878201910280838360005b8381101561178e578181015183820152602001611776565b50505050905001955050505050506000604051808303818588803b1580156117b557600080fd5b505af11580156117c9573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156117f357600080fd5b810190808051604051939291908464010000000082111561181357600080fd5b90830190602082018581111561182857600080fd5b825186602082028301116401000000008211171561184557600080fd5b82525081516020918201928201910280838360005b8381101561187257818101518382015260200161185a565b505050509050016040525050505060005b848110156118a0576118984382900340613641565b600101611883565b50506001600b55505050565b600a5460ff1690565b600061127282604051806060016040528060298152602001614a076029913960029190613781565b60098054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561109e5780601f106110735761010080835404028352916020019161109e565b60006001600160a01b0382166119855760405162461bcd60e51b815260040180806020018281038252602a8152602001806149dd602a913960400191505060405180910390fd5b6001600160a01b038216600090815260016020526040902061127290613367565b6119ae6132f5565b6001600160a01b03166119bf611a67565b6001600160a01b031614611a08576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b600a5460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600a8054610100600160a81b0319169055565b600e546001600160a01b031681565b600a5461010090046001600160a01b031690565b336001600160a01b037f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb79521614611af8576040805162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00604482015290519081900360640190fd5b611b02828261378e565b5050565b60078054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561109e5780601f106110735761010080835404028352916020019161109e565b611b6f6132f5565b6001600160a01b0316826001600160a01b03161415611bd5576040805162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015290519081900360640190fd5b8060056000611be26132f5565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff191692151592909217909155611c266132f5565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b611c7d611c776132f5565b83613372565b611cb85760405162461bcd60e51b8152600401808060200182810382526031815260200180614f476031913960400191505060405180910390fd5b611cc4848484846137ea565b50505050565b611cd26132f5565b6001600160a01b0316611ce3611a67565b6001600160a01b031614611d2c576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b61140961383c565b6060611d3f82612cf5565b611d7a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614b9d602f913960400191505060405180910390fd5b6060611d846118dd565b90506000815111611da45760405180602001604052806000815250611e6e565b80611dae84612d50565b6040516020018083805190602001908083835b60208310611de05780518252601f199092019160209182019101611dc1565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310611e285780518252601f199092019160209182019101611e09565b6001836020036101000a0380198251168184511680821785525050505050509050018064173539b7b760d91b815250600501925050506040516020818303038152906040525b9392505050565b611e7d6132f5565b6001600160a01b0316611e8e611a67565b6001600160a01b031614611ed7576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b601055565b6060611ee782612cf5565b611f38576040805162461bcd60e51b815260206004820152601b60248201527f6d657461646174613a206e6f6e6578697374656e7420746f6b656e0000000000604482015290519081900360640190fd5b6000828152601f6020526040902054611f98576040805162461bcd60e51b815260206004820152601f60248201527f6d657461646174613a20646e61206e6f74207965742067656e65726174656400604482015290519081900360640190fd5b611fa0614518565b6000838152601f6020526040902054611fb890612d02565b9050611fc2614537565b60408051610100808201808452855160ff166000908152601760209081529085902061014085018652805460a01b6001600160a01b0319168352600180820180548851600293821615909702600019011691909104601f8101849004840286018401909752868552949586959394919361012087019390919083018282801561208c5780601f106120615761010080835404028352916020019161208c565b820191906000526020600020905b81548152906001019060200180831161206f57829003601f168201915b50505091909252505050815260208481015160ff1660009081526018825260409081902081518083018352815460a01b6001600160a01b0319168152600180830180548551600261010094831615949094026000190190911692909204601f810187900487028301870190955284825295850195919492938584019391929183018282801561215c5780601f106121315761010080835404028352916020019161215c565b820191906000526020600020905b81548152906001019060200180831161213f57829003601f168201915b50505091909252505050815260408481015160ff166000908152601960209081529082902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f81018690048602830186019096528582529584019591949293858101939192919083018282801561222e5780601f106122035761010080835404028352916020019161222e565b820191906000526020600020905b81548152906001019060200180831161221157829003601f168201915b505050919092525050508152606084015160ff166000908152601a602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252958401959194929385810193919291908301828280156123015780601f106122d657610100808354040283529160200191612301565b820191906000526020600020905b8154815290600101906020018083116122e457829003601f168201915b505050919092525050508152608084015160ff166000908152601b602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252958401959194929385810193919291908301828280156123d45780601f106123a9576101008083540402835291602001916123d4565b820191906000526020600020905b8154815290600101906020018083116123b757829003601f168201915b50505091909252505050815260a08481015160ff166000908152601c602090815260409182902082518084018452815490941b6001600160a01b0319168452600180820180548551600261010094831615949094026000190190911692909204601f8101859004850283018501909552848252958301959193858401939192918301828280156124a55780601f1061247a576101008083540402835291602001916124a5565b820191906000526020600020905b81548152906001019060200180831161248857829003601f168201915b50505091909252505050815260c084015160ff166000908152601d602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252958401959194929385810193919291908301828280156125785780601f1061254d57610100808354040283529160200191612578565b820191906000526020600020905b81548152906001019060200180831161255b57829003601f168201915b50505091909252505050815260e084015160ff166000908152601e602090815260409182902082518084018452815460a01b6001600160a01b0319168152600180830180548651600261010094831615949094026000190190911692909204601f81018690048602830186019096528582529584019591949293858101939192919083018282801561264b5780601f106126205761010080835404028352916020019161264b565b820191906000526020600020905b81548152906001019060200180831161262e57829003601f168201915b50505050508152505081525090506060612663614565565b506040805161014081018252600661010082019081526514dc1a5c9a5d60d21b6101208301528152815180830183526004808252634361706560e01b6020838101919091528084019290925283518085018552600580825264546f72736f60d81b8285015284860191909152845180860186528281526341726d7360e01b81850152606085015284518086018652918252634d61736b60e01b828401526080840191909152835180850185528181526409adeeae8d60db1b8184015260a0840152835180850185526007815266426f74746f6d7360c81b8184015260c08401528351808501909452835264426f6f747360d81b9083015260e081019190915260005b60088110156129a15783816008811061277a57fe5b6020020151516001600160a01b03191661279357612999565b8283516000146127be57604051806040016040528060038152602001622c207b60e81b8152506127d9565b604051806040016040528060018152602001607b60f81b8152505b8383600881106127e557fe5b60200201516128048785600881106127f957fe5b6020020151516138bf565b6040516020018085805190602001908083835b602083106128365780518252601f199092019160209182019101612817565b51815160209384036101000a600019018019909216911617905287519190930192870191508083835b6020831061287e5780518252601f19909201916020918201910161285f565b51815160209384036101000a60001901801990921691161790526e113a3930b4ba2fba3cb832911d101160891b919093019081528551600f90910192860191508083835b602083106128e15780518252601f1990920191602091820191016128c2565b51815160209384036101000a600019018019909216911617905261088b60f21b9190930190815269113b30b63ab2911d101160b11b60028201528451600c90910192850191508083835b6020831061294a5780518252601f19909201916020918201910161292b565b5181516020939093036101000a6000190180199091169216919091179052601160f91b920191825250607d60f81b600182015260408051808303601d1901815260029092019052975050505050505b600101612765565b506129ab86612d50565b6129b4876108b2565b6129bd88612d50565b604051607b60f81b602080830191825272226e616d65223a20224c75636861646f72202360681b602184015285518893603401918701908083835b60208310612a175780518252601f1990920191602091820191016129f8565b5181516020939093036101000a600019018019909116921691909117905261088b60f21b920191825250600201608d614a528239608d01806e1134b6b0b3b2afb230ba30911d101160891b815250600f0184805190602001908083835b60208310612a935780518252601f199092019160209182019101612a74565b5181516020939093036101000a600019018019909116921691909117905261088b60f21b9201918252506002016030614c3e823960300183805190602001908083835b60208310612af55780518252601f199092019160209182019101612ad6565b51815160209384036101000a600019018019909216911617905261088b60f21b919093019081526e2261747472696275746573223a205b60881b60028201528451601190910192850191508083835b60208310612b635780518252601f199092019160209182019101612b44565b5181516020939093036101000a6000190180199091169216919091179052605d60f81b920191825250607d60f81b600182015260408051808303601d19018152600290920190529b9a5050505050505050505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b612bef6132f5565b6001600160a01b0316612c00611a67565b6001600160a01b031614612c49576040805162461bcd60e51b81526020600482018190526024820152600080516020614b54833981519152604482015290519081900360640190fd5b6001600160a01b038116612c8e5760405162461bcd60e51b81526004018080602001828103825260268152602001806148c86026913960400191505060405180910390fd5b600a546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600a80546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b60006112726002836139c5565b612d0a614518565b612d12614518565b60005b600c811015612d4957600a84068282600c8110612d2e57fe5b60ff9092166020929092020152600a84049350600101612d15565b5092915050565b606081612d7557506040805180820190915260018152600360fc1b60208201526108ad565b8160005b8115612d8d57600101600a82049150612d79565b60608167ffffffffffffffff81118015612da657600080fd5b506040519080825280601f01601f191660200182016040528015612dd1576020820181803683370190505b50859350905060001982015b8315612e2257600a840660300160f81b82828060019003935081518110612e0057fe5b60200101906001600160f81b031916908160001a905350600a84049350612ddd565b50949350505050565b6060612e3683612d50565b6013836008602002015160ff1681548110612e4d57fe5b90600052602060002001612e6085612d50565b6014856009602002015160ff1681548110612e7757fe5b90600052602060002001612e8a87612d50565b601587600a602002015160ff1681548110612ea157fe5b90600052602060002001612eb489612d50565b601689600b602002015160ff1681548110612ecb57fe5b90600052602060002001612ede8b612d50565b60405160200180806f1e39ba3cb6329f11b63ab1b430b237b960811b8152506010018a805190602001908083835b60208310612f2b5780518252601f199092019160209182019101612f0c565b6001836020036101000a0380198251168184511680821785525050505050509050018075202e6c756368612d62617365207b2066696c6c3a202360501b81525060160189805460018160011615610100020316600290048015612fc55780601f10612fa3576101008083540402835291820191612fc5565b820191906000526020600020905b815481529060010190602001808311612fb1575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0188805190602001908083835b6020831061300a5780518252601f199092019160209182019101612feb565b6001836020036101000a0380198251168184511680821785525050505050509050018074202e6c756368612d616c74207b2066696c6c3a202360581b815250601501878054600181600116156101000203166002900480156130a35780601f106130815761010080835404028352918201916130a3565b820191906000526020600020905b81548152906001019060200180831161308f575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0186805190602001908083835b602083106130e85780518252601f1990920191602091820191016130c9565b6001836020036101000a0380198251168184511680821785525050505050509050018075202e6c756368612d65796573207b2066696c6c3a202360501b815250601601858054600181600116156101000203166002900480156131825780601f10613160576101008083540402835291820191613182565b820191906000526020600020905b81548152906001019060200180831161316e575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0184805190602001908083835b602083106131c75780518252601f1990920191602091820191016131a8565b6001836020036101000a0380198251168184511680821785525050505050509050018075202e6c756368612d736b696e207b2066696c6c3a202360501b815250601601838054600181600116156101000203166002900480156132615780601f1061323f576101008083540402835291820191613261565b820191906000526020600020905b81548152906001019060200180831161324d575b5050806c1d903e9011b63ab1b430b237b960991b815250600d0182805190602001908083835b602083106132a65780518252601f199092019160209182019101613287565b6001836020036101000a038019825116818451168082178552505050505050905001806146bc60bd913960bd019950505050505050505050604051602081830303815290604052905092915050565b3390565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061332e826118b5565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006112728261363d565b600061337d82612cf5565b6133b85760405162461bcd60e51b815260040180806020018281038252602c815260200180614979602c913960400191505060405180910390fd5b60006133c3836118b5565b9050806001600160a01b0316846001600160a01b031614806133fe5750836001600160a01b03166133f3846110a8565b6001600160a01b0316145b8061340e575061340e8185612bb9565b949350505050565b826001600160a01b0316613429826118b5565b6001600160a01b03161461346e5760405162461bcd60e51b8152600401808060200182810382526029815260200180614b746029913960400191505060405180910390fd5b6001600160a01b0382166134b35760405162461bcd60e51b815260040180806020018281038252602481526020018061492f6024913960400191505060405180910390fd5b6134be8383836139d1565b6134c96000826132f9565b6001600160a01b03831660009081526001602052604090206134eb9082613a20565b506001600160a01b038216600090815260016020526040902061350e9082613a2c565b5061351b60028284613a38565b5080826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600061126f8383613a4e565b600080808061357d8686613ab2565b9097909650945050505050565b6135926118ac565b156135d7576040805162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015290519081900360640190fd5b600a805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861360d6132f5565b604080516001600160a01b039092168252519081900360200190a1565b8051611b0290600990602084019061458d565b5490565b601054604080516370a0823160e01b815230600482015290516001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca16916370a08231916024808301926020929190829003018186803b1580156136aa57600080fd5b505afa1580156136be573d6000803e3d6000fd5b505050506040513d60208110156136d457600080fd5b50511015613729576040805162461bcd60e51b815260206004820152601f60248201527f4e6f7420656e6f756768204c494e4b202d2066696c6c20636f6e747261637400604482015290519081900360640190fd5b600061373a600f5460105484613b2d565b9050613746600d613ce0565b604051806020016040528061375b600d61363d565b90526000828152602080526040902090519055611b023361377c600d61363d565b613ce9565b600061340e848484613d03565b60008281526020808052604080832080548452601f83528184208590559285905281805291548251848152925190927f1d584699e20b45cf7fb70771dbd92bb407c244dd750faf0d3c3108aaae7d0e7292908290030190a25050565b6137f5848484613416565b61380184848484613dcd565b611cc45760405162461bcd60e51b81526004018080602001828103825260328152602001806148966032913960400191505060405180910390fd5b6138446118ac565b61388c576040805162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015290519081900360640190fd5b600a805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61360d6132f5565b606060005b600c8160ff161080156138f25750828160ff16600c81106138e157fe5b1a60f81b6001600160f81b03191615155b156138ff576001016138c4565b60608160ff1667ffffffffffffffff8111801561391b57600080fd5b506040519080825280601f01601f191660200182016040528015613946576020820181803683370190505b509050600091505b600c8260ff1610801561397c5750838260ff16600c811061396b57fe5b1a60f81b6001600160f81b03191615155b15611e6e57838260ff16600c811061399057fe5b1a60f81b818360ff16815181106139a357fe5b60200101906001600160f81b031916908160001a90535060019091019061394e565b600061126f8383613f35565b6139dc8383836111e0565b6139e46118ac565b156111e05760405162461bcd60e51b815260040180806020018281038252602b815260200180614691602b913960400191505060405180910390fd5b600061126f8383613f4d565b600061126f8383614013565b600061340e84846001600160a01b03851661405d565b81546000908210613a905760405162461bcd60e51b81526004018080602001828103825260228152602001806146396022913960400191505060405180910390fd5b826000018281548110613a9f57fe5b9060005260206000200154905092915050565b815460009081908310613af65760405162461bcd60e51b8152600401808060200182810382526022815260200180614a306022913960400191505060405180910390fd5b6000846000018481548110613b0757fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b60007f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316634000aea07f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb795285878660405160200180838152602001828152602001925050506040516020818303038152906040526040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613c09578181015183820152602001613bf1565b50505050905090810190601f168015613c365780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b158015613c5757600080fd5b505af1158015613c6b573d6000803e3d6000fd5b505050506040513d6020811015613c8157600080fd5b50506000848152600c6020526040812054613ca1908690859030906140f4565b6000868152600c6020526040902054909150613cbe90600161413b565b6000868152600c6020526040902055613cd78582614195565b95945050505050565b80546001019055565b611b028282604051806020016040528060008152506141c1565b60008281526001840160205260408120548281613d9e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613d63578181015183820152602001613d4b565b50505050905090810190601f168015613d905780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50846000016001820381548110613db157fe5b9060005260206000209060020201600101549150509392505050565b6000613de1846001600160a01b0316614213565b613ded5750600161340e565b6060613efb630a85bd0160e11b613e026132f5565b88878760405160240180856001600160a01b03168152602001846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613e69578181015183820152602001613e51565b50505050905090810190601f168015613e965780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050604051806060016040528060328152602001614896603291396001600160a01b0388169190614219565b90506000818060200190516020811015613f1457600080fd5b50516001600160e01b031916630a85bd0160e11b1492505050949350505050565b60009081526001919091016020526040902054151590565b600081815260018301602052604081205480156140095783546000198083019190810190600090879083908110613f8057fe5b9060005260206000200154905080876000018481548110613f9d57fe5b600091825260208083209091019290925582815260018981019092526040902090840190558654879080613fcd57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050611272565b6000915050611272565b600061401f8383613f35565b61405557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611272565b506000611272565b6000828152600184016020526040812054806140c2575050604080518082018252838152602080820184815286546001818101895560008981528481209551600290930290950191825591519082015586548684528188019092529290912055611e6e565b828560000160018303815481106140d557fe5b9060005260206000209060020201600101819055506000915050611e6e565b60408051602080820196909652808201949094526001600160a01b039290921660608401526080808401919091528151808403909101815260a09092019052805191012090565b60008282018381101561126f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6141cb8383614228565b6141d86000848484613dcd565b6111e05760405162461bcd60e51b81526004018080602001828103825260328152602001806148966032913960400191505060405180910390fd5b3b151590565b606061340e8484600085614356565b6001600160a01b038216614283576040805162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015290519081900360640190fd5b61428c81612cf5565b156142de576040805162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015290519081900360640190fd5b6142ea600083836139d1565b6001600160a01b038216600090815260016020526040902061430c9082613a2c565b5061431960028284613a38565b5060405181906001600160a01b038416906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060824710156143975760405162461bcd60e51b81526004018080602001828103825260268152602001806149536026913960400191505060405180910390fd5b6143a085614213565b6143f1576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106144305780518252601f199092019160209182019101614411565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614492576040519150601f19603f3d011682016040523d82523d6000602084013e614497565b606091505b50915091506144a78282866144b2565b979650505050505050565b606083156144c1575081611e6e565b8251156144d15782518084602001fd5b60405162461bcd60e51b8152602060048201818152845160248401528451859391928392604401919085019080838360008315613d63578181015183820152602001613d4b565b604051806101800160405280600c906020820280368337509192915050565b6040518061010001604052806008905b61454f61460b565b8152602001906001900390816145475790505090565b6040518061010001604052806008905b60608152602001906001900390816145755790505090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106145ce57805160ff19168380011785556145fb565b828001600101855582156145fb579182015b828111156145fb5782518255916020019190600101906145e0565b50614607929150614623565b5090565b60408051808201909152600081526060602082015290565b5b80821115614607576000815560010161462456fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64733c706174682066696c6c3d272330303027206f7061636974793d272e392720643d274d3133203131682d3376316834762d317a272f3e4552433732315061757361626c653a20746f6b656e207472616e73666572207768696c6520706175736564202e6c756368612d62726561746865207b20616e696d6174696f6e3a20302e3573206c756368612d6272656174686520696e66696e69746520616c7465726e61746520656173652d696e2d6f75743b207d20406b65796672616d6573206c756368612d62726561746865207b2066726f6d207b207472616e73666f726d3a207472616e736c6174655928307078293b207d20746f207b207472616e73666f726d3a207472616e736c61746559283125293b207d207d3c2f7374796c653e3c706174682066696c6c3d27234646462720643d274d39203648367633683456367a4d31372036682d337633683456367a272f3e3c7061746820636c6173733d276c756368612d657965732720643d274d31362036682d327633683356367a4d382036483776336833563648397a272f3e3c706174682066696c6c3d27234646462720643d274d3720366831763148377a4d3136203668317631682d317a27206f7061636974793d272e34272f3e3c706174682066696c6c3d27233030302720643d274d3135203768317631682d317a4d3820376831763148387a272f3e3c7061746820636c6173733d276c756368612d736b696e2720643d274d3136203233762d3648387636483776316834762d34683276346834762d317a272f3e4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573733c7061746820636c6173733d276c756368612d626173652720643d274d31352031374838763168317631683276316832762d316832762d316831762d317a272f3e4552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e6473226465736372697074696f6e223a20224c75636861646f726573206172652072616e646f6d6c792067656e657261746564207573696e6720436861696e6c696e6b2056524620616e6420686176652031303025206f6e2d636861696e2061727420616e64206d65746164617461202d204f6e6c792031303030302077696c6c206576657220657869737421222c4552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e3c7061746820636c6173733d276c756368612d626173652720643d274d3920323148387632483776316834762d33682d317a4d3136203233762d32682d3376336834762d317a272f3e4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65724552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e3c7061746820636c6173733d276c756368612d626173652720643d274d313820355633682d315632682d315631682d3156304839763148387631483776314836763248357635683176326831763168317631683176316836762d316831762d316831762d316831762d32683156357a272f3e2265787465726e616c5f75726c223a202268747470733a2f2f6c75636861646f7265732e696f2f6c75636861646f722f3c7061746820636c6173733d276c756368612d616c742720643d274d313820345633682d315632682d315631682d3156304839763148387631483776314836763248357635683156366831563568325634683156336834763168317631683276316831763468315635682d317a272f3e3c672066696c6c3d2723303030273e3c7061746820643d274d313820345633682d315632682d315631682d3156304839763148387631483776314836763248357635683156356831563468315633683156326836763168317631683176316831763568315635682d317a27206f7061636974793d272e32272f3e3c7061746820643d274d313620345633682d31563248397631483876314837763168325634683156336834763168317631683256347a4d3620356831763148367a4d3137203568317631682d317a27206f7061636974793d272e35272f3e3c2f673e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65726d696e74207175616e74697479206d757374206265206265747765656e20312d32303c7061746820636c6173733d276c756368612d736b696e2720643d274d3232203132762d31682d31762d31682d315639682d315635682d315633682d315632682d315631682d3156304839763148387631483776314836763248357634483476314833763148327631483176386834762d316831762d324835762d336831763168317631683176326838762d326831762d316831762d3168317633682d317632683176316834762d387a272f3e3c7061746820636c6173733d276c756368612d616c742720643d274d32302031305639682d327631682d3176316834762d317a4d35203948347631483376316834762d31483656397a272f3e3c706174682066696c6c3d272330303027206f7061636974793d272e322720643d274d36203948347631483376316834762d3148367a4d32302031305639682d327631682d3176316834762d317a272f3e4552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f7665642720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323030302f737667272076696577426f783d27302030203234203234273e3c7061746820636c6173733d276c756368612d736b696e2720643d274d3134203130483976336836762d337a272f3ea2646970667358221220f07ff78f47503188bddd1cb2cc6410513aab09c35bef87db8e84d77cf54338e964736f6c634300060c0033
Loading...
Loading
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.