Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,471 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Feed | 41909863 | 1091 days ago | IN | 0 POL | 0.29144005 | ||||
| Feed | 41257794 | 1108 days ago | IN | 0 POL | 0.09080319 | ||||
| Feed | 39994993 | 1142 days ago | IN | 0 POL | 0.08879306 | ||||
| Feed | 39994966 | 1142 days ago | IN | 0 POL | 0.08571018 | ||||
| Feed | 39994944 | 1142 days ago | IN | 0 POL | 0.07551288 | ||||
| Feed | 39994922 | 1142 days ago | IN | 0 POL | 0.05909391 | ||||
| Feed | 39994905 | 1142 days ago | IN | 0 POL | 0.05585868 | ||||
| Feed | 39994886 | 1142 days ago | IN | 0 POL | 0.05198415 | ||||
| Upgrade | 39786983 | 1147 days ago | IN | 0 POL | 0.0320273 | ||||
| Upgrade | 39786957 | 1147 days ago | IN | 0 POL | 0.01810878 | ||||
| Feed Egg | 39786940 | 1147 days ago | IN | 0 POL | 0.02167781 | ||||
| Feed | 39786916 | 1147 days ago | IN | 0 POL | 0.05684417 | ||||
| Feed Egg | 38227754 | 1188 days ago | IN | 0 POL | 0.06859218 | ||||
| Fuse | 38227719 | 1188 days ago | IN | 0 POL | 0.01990159 | ||||
| Fuse | 38227703 | 1188 days ago | IN | 0 POL | 0.01992096 | ||||
| Fuse | 38227683 | 1188 days ago | IN | 0 POL | 0.0198342 | ||||
| Fuse | 38227660 | 1188 days ago | IN | 0 POL | 0.0186483 | ||||
| Fuse | 38227646 | 1188 days ago | IN | 0 POL | 0.01924219 | ||||
| Fuse | 38117129 | 1190 days ago | IN | 0 POL | 0.01673002 | ||||
| Feed | 38117050 | 1190 days ago | IN | 0 POL | 0.06337745 | ||||
| Feed | 38117039 | 1190 days ago | IN | 0 POL | 0.06138348 | ||||
| Feed | 38117018 | 1190 days ago | IN | 0 POL | 0.06738003 | ||||
| Feed | 37994166 | 1193 days ago | IN | 0 POL | 0.10486611 | ||||
| Feed | 37961765 | 1194 days ago | IN | 0 POL | 0.03922883 | ||||
| Feed | 37931126 | 1195 days ago | IN | 0 POL | 0.03018806 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
GooFeeding
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 2266 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
// | \/ (_) | _ \ | | | (_)
// | \ / |_ ___ _ __ ___ | |_) |_ _ __| | __| |_ ___ ___ ™
// | |\/| | |/ __| '__/ _ \| _ <| | | |/ _` |/ _` | |/ _ \/ __|
// | | | | | (__| | | (_) | |_) | |_| | (_| | (_| | | __/\__ \
// |_| |_|_|\___|_| \___/|____/ \__,_|\__,_|\__,_|_|\___||___/ 2022
import "./interfaces/IBuddyCore.sol";
import "./interfaces/IGoo.sol";
import "./ERC721Full.sol";
import "@prb/math/contracts/PRBMathSD59x18.sol";
contract GooFeeding is ERC721Full {
IBuddyCore public buddyContract;
IGoo public goo;
mapping(uint256 => WaterBear) public bears;
mapping(address => uint256) public hatchery;
uint256 public feedTime;
uint256 public cost0 = 100000;
uint256 public cost1 = 150000;
uint256 public cost2 = 200000;
uint256 public cost3 = 250000;
struct WaterBear {
DNA dna;
uint256 fed;
address owner;
}
event Feed(
uint256 indexed tokenId,
uint256 indexed owner,
uint256 indexed amount
);
event EggFeed(uint256 indexed tokenId, uint256 indexed amount);
event Upgrade(address indexed owner, uint256 indexed newLevel);
event Fuse(
uint256 indexed eggId1,
uint256 indexed eggId2,
uint256 indexed eggId3
);
constructor(address _buddyCoreAddr, address _gooContractAddr) {
buddyContract = IBuddyCore(_buddyCoreAddr);
goo = IGoo(_gooContractAddr);
feedTime = block.timestamp;
}
modifier onlyWaterBearHolder(uint256 _tokenId) {
WaterBear memory wb = bears[_tokenId];
require(msg.sender == wb.owner, "Unauthorized");
_;
}
modifier spawnable(uint256 wbid) {
uint256[] memory tokens = getTokensByParent(wbid);
for (uint256 i = 0; i < tokens.length; i++) {
Egg memory egg = _data[tokens[i]];
if (egg.rarity == RARITY.COMMON && egg.parent == wbid) {
require(
(block.timestamp > feedTime &&
block.timestamp - feedTime >= 24 hours) ||
(feedTime > egg.spawnTime &&
feedTime - egg.spawnTime >= 24 hours),
"Bear needs time before spawning another egg!"
);
}
}
_;
}
modifier whenNotLocked(uint256 _tokenId) {
uint8 lock = buddyContract.isLocked(_tokenId);
require(lock == 2, lock == 0 ? "Buddy locked" : "Unlocking");
_;
}
function setBuddyContract(address _buddyCoreAddr) external onlyOwner {
buddyContract = IBuddyCore(_buddyCoreAddr);
}
function setGooContract(address _gooContractAddr) external onlyOwner {
goo = IGoo(_gooContractAddr);
}
function spendGOO(uint256[] calldata mbids, uint256 cost)
private
returns (uint256 totalFeed)
{
uint256 totalBalance;
for (uint256 i = 0; i < mbids.length; i++) {
require(
msg.sender == buddyContract.getOwnerOf(mbids[i]) ||
msg.sender == buddyContract.getApproval(mbids[i]),
"Not approved to spend GOO"
);
totalBalance += goo.balanceOf(mbids[i]);
if (totalBalance >= cost) {
break;
}
}
require(totalBalance >= cost, "Not enough GOO!");
totalFeed = cost;
for (uint256 i = 0; i < mbids.length; i++) {
uint256 id = mbids[i];
uint256 balance = goo.balanceOf(id);
address _owner = buddyContract.getOwnerOf(id);
if (balance < cost) {
buddyContract.transferFrom(_owner, address(this), id);
goo.burn(id, balance);
buddyContract.transferFrom(address(this), _owner, id);
cost -= balance;
} else {
buddyContract.transferFrom(_owner, address(this), id);
goo.burn(id, cost);
buddyContract.transferFrom(address(this), _owner, id);
break;
}
}
}
function bearOwnerOf(uint256 _tokenId) external view returns (address) {
WaterBear memory wb = bears[_tokenId];
return wb.owner;
}
function setBears(
uint256[] calldata ids,
DNA[] calldata DNAs,
address[] calldata owners
) external onlyOwner {
for (uint256 i = 0; i < ids.length; i++) {
setBear(ids[i], DNAs[i], owners[i]);
}
}
function setBear(
uint256 id,
DNA _DNA,
address _owner
) public onlyOwner {
WaterBear memory bear;
bear.dna = _DNA;
bear.owner = _owner;
bears[id] = bear;
}
function setCosts(
uint256 _cost0,
uint256 _cost1,
uint256 _cost2,
uint256 _cost3
) external onlyOwner {
cost0 = _cost0;
cost1 = _cost1;
cost2 = _cost2;
cost3 = _cost3;
}
function getCost(DNA _DNA) public view returns (uint256 GOO) {
if (uint256(_DNA) == 0) {
GOO = cost0 * 1e18;
} else if (uint256(_DNA) == 1) {
GOO = cost1 * 1e18;
} else if (uint256(_DNA) == 2) {
GOO = cost2 * 1e18;
} else if (uint256(_DNA) >= 3) {
GOO = cost3 * 1e18;
}
}
function feed(uint256[] calldata mbids, uint256 wbid)
external
whenNotPaused
onlyWaterBearHolder(wbid)
spawnable(wbid)
{
while (
block.timestamp > feedTime && block.timestamp - feedTime > 24 hours
) {
feedTime += 24 hours;
}
WaterBear storage bear = bears[wbid];
uint256 cost = getCost(bear.dna);
uint256 totalFeed = spendGOO(mbids, cost);
bear.fed += totalFeed;
uint256 tokenId = safeMint(msg.sender);
Egg memory egg;
egg.rarity = RARITY.COMMON;
egg.dna = bear.dna;
egg.spawnTime = block.timestamp;
egg.parent = wbid;
egg.maxLevel = getBaseMaxLevel(egg.dna);
_data[tokenId] = egg;
_addParentToEggEnumeration(wbid, tokenId);
emit Feed(tokenId, wbid, totalFeed);
}
// ______ ______ _ _
// | ____| | ____| | (_)
// | |__ __ _ __ _ | |__ ___ ___ __| |_ _ __ __ _
// | __| / _` |/ _` | | __/ _ \/ _ \/ _` | | '_ \ / _` |
// | |___| (_| | (_| | | | | __/ __/ (_| | | | | | (_| |
// |______\__, |\__, | |_| \___|\___|\__,_|_|_| |_|\__, |
// __/ | __/ | __/ |
// |___/ |___/ |___/
uint16 public maxLevel0 = 30;
uint16 public maxLevel1 = 35;
uint16 public maxLevel2 = 40;
uint16 public maxLevel3 = 50;
modifier onlyHolder(uint256 _tokenId) {
require(msg.sender == ownerOf(_tokenId), "Unauthorized");
_;
}
function getEgg(uint256 _tokenId)
external
view
returns (
DNA,
RARITY,
uint16,
uint16,
uint256,
uint256,
uint256
)
{
Egg storage egg = _data[_tokenId];
return (
egg.dna,
egg.rarity,
egg.level,
egg.maxLevel,
egg.totalFeed,
egg.spawnTime,
egg.parent
);
}
function getTokensByParent(uint256 wbid)
public
view
returns (uint256[] memory)
{
uint256 tokenCount = eggBalanceOf(wbid);
if (tokenCount == 0) {
return new uint256[](0);
} else {
uint256[] memory result = new uint256[](tokenCount);
for (uint256 i = 0; i < tokenCount; i++) {
uint256 tokenId = eggOfOwnerByIndex(wbid, i);
result[i] = tokenId;
}
return result;
}
}
function setMaxLevels(
uint16 _maxLevel0,
uint16 _maxLevel1,
uint16 _maxLevel2,
uint16 _maxLevel3
) external onlyOwner {
maxLevel0 = _maxLevel0;
maxLevel1 = _maxLevel1;
maxLevel2 = _maxLevel2;
maxLevel3 = _maxLevel3;
}
function getBaseMaxLevel(DNA _DNA) public view returns (uint16 maxLevel) {
if (uint256(_DNA) == 0) {
maxLevel = maxLevel0;
} else if (uint256(_DNA) == 1) {
maxLevel = maxLevel1;
} else if (uint256(_DNA) == 2) {
maxLevel = maxLevel2;
} else if (uint256(_DNA) >= 3) {
maxLevel = maxLevel3;
}
}
function feedEgg(
uint256[] calldata mbids,
uint256 eggId,
uint256 amount
) external whenNotPaused onlyHolder(eggId) {
Egg storage egg = _data[eggId];
uint256 cost = amount * 1e18;
uint256 maxLevel = getMaxLevel(eggId);
uint256 maxGoo = getGOOToLevel(egg.dna, maxLevel) - egg.totalFeed;
require(
egg.level < maxLevel && maxGoo > 0,
"Egg at max level! Try fusing."
);
uint256 totalFeed;
for (uint256 i = 0; i < mbids.length; i++) {
uint256 id = mbids[i];
address _owner = buddyContract.getOwnerOf(id);
require(
msg.sender == _owner ||
msg.sender == buddyContract.getApproval(id),
"Not approved to spend GOO"
);
uint256 balance = goo.balanceOf(id);
if (totalFeed + balance > cost) {
balance = cost - totalFeed;
}
if (totalFeed + balance > maxGoo) {
balance = maxGoo - totalFeed;
}
buddyContract.transferFrom(_owner, address(this), id);
goo.burn(id, balance);
buddyContract.transferFrom(address(this), _owner, id);
totalFeed += balance;
if (totalFeed >= maxGoo || totalFeed >= cost) {
break;
}
}
egg.level = getLevel(eggId, totalFeed);
egg.totalFeed += totalFeed;
emit EggFeed(eggId, totalFeed);
}
function getGOOToLevel(DNA dna, uint256 level)
public
view
returns (uint256 gooToLevel)
{
int256 base = int256(getCost(dna)) / 1e18 / 100;
int256 rate = base *
PRBMathSD59x18.div(
1 ether - PRBMathSD59x18.powu(1.05 ether, level),
-0.05 ether
);
gooToLevel = uint256(rate);
}
function getGOOForLevel(DNA dna, uint256 level)
external
view
returns (uint256 gooForLevel)
{
int256 base = int256(getCost(dna)) / 1e18 / 100;
int256 rate = base * PRBMathSD59x18.powu(1.05 ether, level);
gooForLevel = uint256(rate);
}
function getLevel(uint256 eggId, uint256 GOO)
public
view
returns (uint16 level)
{
Egg memory egg = _data[eggId];
if (GOO == 0) {
return egg.level;
}
uint256 balancer = (getCost(egg.dna) * 20) / 100;
int256 totalGOO = int256(egg.totalFeed + GOO + balancer);
int256 step = PRBMathSD59x18.div(totalGOO, int256(balancer));
int256 currentLog = PRBMathSD59x18.div(
PRBMathSD59x18.ln(step),
PRBMathSD59x18.ln(1.05 ether)
);
level = uint16(int16(currentLog / 1e18));
}
function getMaxLevel(uint256 eggId) public view returns (uint256 maxLevel) {
Egg memory egg = _data[eggId];
maxLevel = egg.maxLevel;
}
// _ _ _ _
// | | | | | | | |
// | |__| | __ _| |_ ___| |__ ___ _ __ _ _
// | __ |/ _` | __/ __| '_ \ / _ \ '__| | | |
// | | | | (_| | || (__| | | | __/ | | |_| |
// |_| |_|\__,_|\__\___|_| |_|\___|_| \__, |
// __/ |
// |___/
uint256 public maxHatchery = 5;
uint256 public hatcheryCost0 = 50000;
uint256 public hatcheryCost1 = 250000;
uint256 public hatcheryCost2 = 1000000;
uint256 public hatcheryCost3 = 5000000;
uint256 public hatcheryCost4 = 50000000;
function setMaxHatchery(uint256 _maxHatchery) external onlyOwner {
maxHatchery = _maxHatchery;
}
function setHatcheryCosts(
uint256 _hatcheryCost0,
uint256 _hatcheryCost1,
uint256 _hatcheryCost2,
uint256 _hatcheryCost3,
uint256 _hatcheryCost4
) external onlyOwner {
hatcheryCost0 = _hatcheryCost0;
hatcheryCost1 = _hatcheryCost1;
hatcheryCost2 = _hatcheryCost2;
hatcheryCost3 = _hatcheryCost3;
hatcheryCost4 = _hatcheryCost4;
}
function getHatcheryCost(uint256 level) public view returns (uint256 cost) {
if (level == 0) {
cost = hatcheryCost0 * 1e18;
} else if (level == 1) {
cost = hatcheryCost1 * 1e18;
} else if (level == 2) {
cost = hatcheryCost2 * 1e18;
} else if (level == 3) {
cost = hatcheryCost3 * 1e18;
} else {
cost = hatcheryCost4 * (level - 3) * 1e18;
}
}
function upgrade(uint256[] calldata mbids) external whenNotPaused {
uint256 currLevel = hatchery[msg.sender];
require(currLevel < maxHatchery, "Hatchery is max level");
uint256 cost = getHatcheryCost(currLevel);
spendGOO(mbids, cost);
hatchery[msg.sender] += 1;
emit Upgrade(msg.sender, currLevel + 1);
}
// ______ ______ _
// | ____| | ____| (_)
// | |__ __ _ __ _ | |__ _ _ ___ _ _ __ __ _
// | __| / _` |/ _` | | __| | | / __| | '_ \ / _` |
// | |___| (_| | (_| | | | | |_| \__ \ | | | | (_| |
// |______\__, |\__, | |_| \__,_|___/_|_| |_|\__, |
// __/ | __/ | __/ |
// |___/ |___/ |___/
function fuse(uint256 eggId1, uint256 eggId2)
external
whenNotPaused
onlyHolder(eggId1)
onlyHolder(eggId2)
{
Egg memory egg1 = _data[eggId1];
Egg memory egg2 = _data[eggId2];
require(egg1.rarity == egg2.rarity, "Eggs must be the same rarity!");
require(egg1.dna == egg2.dna, "Eggs must be the same DNA!");
require(uint256(egg1.dna) < 4, "Divines cannot be fused!");
require(
hatchery[msg.sender] > uint256(egg1.rarity),
"Hatchery level too low!"
);
transferFrom(
msg.sender,
address(0x000000000000000000000000000000000000dEaD),
eggId1
);
transferFrom(
msg.sender,
address(0x000000000000000000000000000000000000dEaD),
eggId2
);
uint256 eggId3 = safeMint(msg.sender);
Egg memory egg;
egg.dna = egg1.dna;
egg.rarity = RARITY(uint256(egg1.rarity) + 1);
egg.level = (egg1.level + egg2.level) / 2;
egg.maxLevel = egg.level + 50;
egg.totalFeed = (egg1.totalFeed + egg2.totalFeed) / 2;
egg.spawnTime = block.timestamp;
egg.parent = egg1.parent;
_data[eggId3] = egg;
_addParentToEggEnumeration(egg.parent, eggId3);
emit Fuse(eggId1, eggId2, eggId3);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
pragma solidity 0.8.17;
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IBuddyCore {
function getApproval(uint256) external view returns (address);
function getOwnerOf(uint256) external view returns (address);
function isLocked(uint256) external view returns (uint8);
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IGoo {
function balanceOf(uint256 buddy) external view returns (uint256);
function burn(uint256 buddy, uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
// | \/ (_) | _ \ | | | (_)
// | \ / |_ ___ _ __ ___ | |_) |_ _ __| | __| |_ ___ ___ ™
// | |\/| | |/ __| '__/ _ \| _ <| | | |/ _` |/ _` | |/ _ \/ __|
// | | | | | (__| | | (_) | |_) | |_| | (_| | (_| | | __/\__ \
// |_| |_|_|\___|_| \___/|____/ \__,_|\__,_|\__,_|_|\___||___/ 2022
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract ERC721Full is ERC721Enumerable, ERC721URIStorage, Pausable, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
uint256 private _nonce;
string public BASE_URI = "https://api.microbuddies.io/";
enum DNA {
STANDARD,
SERF,
INVISIBLE,
ICE,
DARK
}
enum RARITY {
COMMON,
RARE,
LEGENDARY,
EXALTED,
DIVINE
}
// Mapping to store all eggs.
mapping(uint256 => Egg) internal _data;
// Mapping from Water Bear parent to list of children egg IDs
mapping(uint256 => mapping(uint256 => uint256)) internal _ownedEggs;
// Mapping Water Bear parent to children count
mapping(uint256 => uint256) internal _eggBalances;
struct Egg {
DNA dna;
RARITY rarity;
uint16 level;
uint16 maxLevel;
uint256 totalFeed;
uint256 spawnTime;
uint256 parent;
}
constructor() ERC721("Water Bear GOO Baby Egg", "WBGBE") {}
function safeMint(address to) internal returns (uint256 tokenId) {
uint256 current = getTokenId();
_safeMint(to, current);
_setTokenURI(
current,
string(abi.encodePacked(Strings.toString(current), ".json"))
);
_tokenIdCounter.increment();
return current;
}
function getTokenId() internal view returns (uint256 tokenId) {
return _tokenIdCounter.current();
}
function setBaseURI(string memory baseURI) public onlyOwner {
BASE_URI = baseURI;
}
function _baseURI() internal view override returns (string memory) {
return BASE_URI;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function approve(address to, uint256 tokenId)
public
override(ERC721, IERC721)
{
super.approve(to, tokenId);
}
function _isApprovedOrOwner(address spender, uint256 tokenId)
internal
view
override
returns (bool)
{
return super._isApprovedOrOwner(spender, tokenId);
}
/**
* Override isApprovedForAll to auto-approve OS's proxy contract
*/
function isApprovedForAll(address _owner, address _operator)
public
view
override(ERC721, IERC721)
returns (bool isOperator)
{
// if OpenSea's ERC721 Proxy Address is detected, auto-return true
if (_operator == address(0x58807baD0B376efc12F5AD86aAc70E78ed67deaE)) {
return true;
}
// otherwise, use the default ERC721.isApprovedForAll()
return ERC721.isApprovedForAll(_owner, _operator);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override(ERC721, ERC721Enumerable) whenNotPaused {
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId)
internal
override(ERC721, ERC721URIStorage)
{
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
string memory baseURI = _baseURI();
Egg memory egg = _data[tokenId];
uint256 _dna = uint256(egg.dna);
uint256 _rarity = uint256(egg.rarity);
string memory eggDNA = "standard";
string memory eggRarity = "common";
if (_dna == 1) {
eggDNA = "serf";
} else if (_dna == 2) {
eggDNA = "invisible";
} else if (_dna == 3) {
eggDNA = "ice";
} else if (_dna == 4) {
eggDNA = "dark";
}
if (_rarity == 1) {
eggRarity = "rare";
} else if (_rarity == 2) {
eggRarity = "legendary";
} else if (_rarity == 3) {
eggRarity = "exalted";
} else if (_rarity == 4) {
eggRarity = "divine";
}
return
bytes(baseURI).length > 0
? string(
abi.encodePacked(baseURI, eggDNA, eggRarity, "wbegg.json")
)
: "";
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
function eggBalanceOf(uint256 wbid) public view virtual returns (uint256) {
return _eggBalances[wbid];
}
function eggOfOwnerByIndex(uint256 wbid, uint256 index)
public
view
virtual
returns (uint256)
{
require(index < eggBalanceOf(wbid), "Egg owner index out of bounds");
return _ownedEggs[wbid][index];
}
/**
* @dev Private function to add a token to this extension's parent-tracking data structures.
* @param wbid representing the parent of the given egg ID
* @param eggid uint256 ID of the token to be added to the tokens list of the given address
*/
function _addParentToEggEnumeration(uint256 wbid, uint256 eggid) internal {
uint256 length = eggBalanceOf(wbid);
_ownedEggs[wbid][length] = eggid;
_eggBalances[wbid] = length + 1;
}
}// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;
import "./PRBMath.sol";
/// @title PRBMathSD59x18
/// @author Paul Razvan Berg
/// @notice Smart contract library for advanced fixed-point math that works with int256 numbers considered to have 18
/// trailing decimals. We call this number representation signed 59.18-decimal fixed-point, since the numbers can have
/// a sign and there can be up to 59 digits in the integer part and up to 18 decimals in the fractional part. The numbers
/// are bound by the minimum and the maximum values permitted by the Solidity type int256.
library PRBMathSD59x18 {
/// @dev log2(e) as a signed 59.18-decimal fixed-point number.
int256 internal constant LOG2_E = 1_442695040888963407;
/// @dev Half the SCALE number.
int256 internal constant HALF_SCALE = 5e17;
/// @dev The maximum value a signed 59.18-decimal fixed-point number can have.
int256 internal constant MAX_SD59x18 =
57896044618658097711785492504343953926634992332820282019728_792003956564819967;
/// @dev The maximum whole value a signed 59.18-decimal fixed-point number can have.
int256 internal constant MAX_WHOLE_SD59x18 =
57896044618658097711785492504343953926634992332820282019728_000000000000000000;
/// @dev The minimum value a signed 59.18-decimal fixed-point number can have.
int256 internal constant MIN_SD59x18 =
-57896044618658097711785492504343953926634992332820282019728_792003956564819968;
/// @dev The minimum whole value a signed 59.18-decimal fixed-point number can have.
int256 internal constant MIN_WHOLE_SD59x18 =
-57896044618658097711785492504343953926634992332820282019728_000000000000000000;
/// @dev How many trailing decimals can be represented.
int256 internal constant SCALE = 1e18;
/// INTERNAL FUNCTIONS ///
/// @notice Calculate the absolute value of x.
///
/// @dev Requirements:
/// - x must be greater than MIN_SD59x18.
///
/// @param x The number to calculate the absolute value for.
/// @param result The absolute value of x.
function abs(int256 x) internal pure returns (int256 result) {
unchecked {
if (x == MIN_SD59x18) {
revert PRBMathSD59x18__AbsInputTooSmall();
}
result = x < 0 ? -x : x;
}
}
/// @notice Calculates the arithmetic average of x and y, rounding down.
/// @param x The first operand as a signed 59.18-decimal fixed-point number.
/// @param y The second operand as a signed 59.18-decimal fixed-point number.
/// @return result The arithmetic average as a signed 59.18-decimal fixed-point number.
function avg(int256 x, int256 y) internal pure returns (int256 result) {
// The operations can never overflow.
unchecked {
int256 sum = (x >> 1) + (y >> 1);
if (sum < 0) {
// If at least one of x and y is odd, we add 1 to the result. This is because shifting negative numbers to the
// right rounds down to infinity.
assembly {
result := add(sum, and(or(x, y), 1))
}
} else {
// If both x and y are odd, we add 1 to the result. This is because if both numbers are odd, the 0.5
// remainder gets truncated twice.
result = sum + (x & y & 1);
}
}
}
/// @notice Yields the least greatest signed 59.18 decimal fixed-point number greater than or equal to x.
///
/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be less than or equal to MAX_WHOLE_SD59x18.
///
/// @param x The signed 59.18-decimal fixed-point number to ceil.
/// @param result The least integer greater than or equal to x, as a signed 58.18-decimal fixed-point number.
function ceil(int256 x) internal pure returns (int256 result) {
if (x > MAX_WHOLE_SD59x18) {
revert PRBMathSD59x18__CeilOverflow(x);
}
unchecked {
int256 remainder = x % SCALE;
if (remainder == 0) {
result = x;
} else {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.
result = x - remainder;
if (x > 0) {
result += SCALE;
}
}
}
}
/// @notice Divides two signed 59.18-decimal fixed-point numbers, returning a new signed 59.18-decimal fixed-point number.
///
/// @dev Variant of "mulDiv" that works with signed numbers. Works by computing the signs and the absolute values separately.
///
/// Requirements:
/// - All from "PRBMath.mulDiv".
/// - None of the inputs can be MIN_SD59x18.
/// - The denominator cannot be zero.
/// - The result must fit within int256.
///
/// Caveats:
/// - All from "PRBMath.mulDiv".
///
/// @param x The numerator as a signed 59.18-decimal fixed-point number.
/// @param y The denominator as a signed 59.18-decimal fixed-point number.
/// @param result The quotient as a signed 59.18-decimal fixed-point number.
function div(int256 x, int256 y) internal pure returns (int256 result) {
if (x == MIN_SD59x18 || y == MIN_SD59x18) {
revert PRBMathSD59x18__DivInputTooSmall();
}
// Get hold of the absolute values of x and y.
uint256 ax;
uint256 ay;
unchecked {
ax = x < 0 ? uint256(-x) : uint256(x);
ay = y < 0 ? uint256(-y) : uint256(y);
}
// Compute the absolute value of (x*SCALE)÷y. The result must fit within int256.
uint256 rAbs = PRBMath.mulDiv(ax, uint256(SCALE), ay);
if (rAbs > uint256(MAX_SD59x18)) {
revert PRBMathSD59x18__DivOverflow(rAbs);
}
// Get the signs of x and y.
uint256 sx;
uint256 sy;
assembly {
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
}
// XOR over sx and sy. This is basically checking whether the inputs have the same sign. If yes, the result
// should be positive. Otherwise, it should be negative.
result = sx ^ sy == 1 ? -int256(rAbs) : int256(rAbs);
}
/// @notice Returns Euler's number as a signed 59.18-decimal fixed-point number.
/// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).
function e() internal pure returns (int256 result) {
result = 2_718281828459045235;
}
/// @notice Calculates the natural exponent of x.
///
/// @dev Based on the insight that e^x = 2^(x * log2(e)).
///
/// Requirements:
/// - All from "log2".
/// - x must be less than 133.084258667509499441.
///
/// Caveats:
/// - All from "exp2".
/// - For any x less than -41.446531673892822322, the result is zero.
///
/// @param x The exponent as a signed 59.18-decimal fixed-point number.
/// @return result The result as a signed 59.18-decimal fixed-point number.
function exp(int256 x) internal pure returns (int256 result) {
// Without this check, the value passed to "exp2" would be less than -59.794705707972522261.
if (x < -41_446531673892822322) {
return 0;
}
// Without this check, the value passed to "exp2" would be greater than 192.
if (x >= 133_084258667509499441) {
revert PRBMathSD59x18__ExpInputTooBig(x);
}
// Do the fixed-point multiplication inline to save gas.
unchecked {
int256 doubleScaleProduct = x * LOG2_E;
result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);
}
}
/// @notice Calculates the binary exponent of x using the binary fraction method.
///
/// @dev See https://ethereum.stackexchange.com/q/79903/24693.
///
/// Requirements:
/// - x must be 192 or less.
/// - The result must fit within MAX_SD59x18.
///
/// Caveats:
/// - For any x less than -59.794705707972522261, the result is zero.
///
/// @param x The exponent as a signed 59.18-decimal fixed-point number.
/// @return result The result as a signed 59.18-decimal fixed-point number.
function exp2(int256 x) internal pure returns (int256 result) {
// This works because 2^(-x) = 1/2^x.
if (x < 0) {
// 2^59.794705707972522262 is the maximum number whose inverse does not truncate down to zero.
if (x < -59_794705707972522261) {
return 0;
}
// Do the fixed-point inversion inline to save gas. The numerator is SCALE * SCALE.
unchecked {
result = 1e36 / exp2(-x);
}
} else {
// 2^192 doesn't fit within the 192.64-bit format used internally in this function.
if (x >= 192e18) {
revert PRBMathSD59x18__Exp2InputTooBig(x);
}
unchecked {
// Convert x to the 192.64-bit fixed-point format.
uint256 x192x64 = (uint256(x) << 64) / uint256(SCALE);
// Safe to convert the result to int256 directly because the maximum input allowed is 192.
result = int256(PRBMath.exp2(x192x64));
}
}
}
/// @notice Yields the greatest signed 59.18 decimal fixed-point number less than or equal to x.
///
/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
///
/// Requirements:
/// - x must be greater than or equal to MIN_WHOLE_SD59x18.
///
/// @param x The signed 59.18-decimal fixed-point number to floor.
/// @param result The greatest integer less than or equal to x, as a signed 58.18-decimal fixed-point number.
function floor(int256 x) internal pure returns (int256 result) {
if (x < MIN_WHOLE_SD59x18) {
revert PRBMathSD59x18__FloorUnderflow(x);
}
unchecked {
int256 remainder = x % SCALE;
if (remainder == 0) {
result = x;
} else {
// Solidity uses C fmod style, which returns a modulus with the same sign as x.
result = x - remainder;
if (x < 0) {
result -= SCALE;
}
}
}
}
/// @notice Yields the excess beyond the floor of x for positive numbers and the part of the number to the right
/// of the radix point for negative numbers.
/// @dev Based on the odd function definition. https://en.wikipedia.org/wiki/Fractional_part
/// @param x The signed 59.18-decimal fixed-point number to get the fractional part of.
/// @param result The fractional part of x as a signed 59.18-decimal fixed-point number.
function frac(int256 x) internal pure returns (int256 result) {
unchecked {
result = x % SCALE;
}
}
/// @notice Converts a number from basic integer form to signed 59.18-decimal fixed-point representation.
///
/// @dev Requirements:
/// - x must be greater than or equal to MIN_SD59x18 divided by SCALE.
/// - x must be less than or equal to MAX_SD59x18 divided by SCALE.
///
/// @param x The basic integer to convert.
/// @param result The same number in signed 59.18-decimal fixed-point representation.
function fromInt(int256 x) internal pure returns (int256 result) {
unchecked {
if (x < MIN_SD59x18 / SCALE) {
revert PRBMathSD59x18__FromIntUnderflow(x);
}
if (x > MAX_SD59x18 / SCALE) {
revert PRBMathSD59x18__FromIntOverflow(x);
}
result = x * SCALE;
}
}
/// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.
///
/// @dev Requirements:
/// - x * y must fit within MAX_SD59x18, lest it overflows.
/// - x * y cannot be negative.
///
/// @param x The first operand as a signed 59.18-decimal fixed-point number.
/// @param y The second operand as a signed 59.18-decimal fixed-point number.
/// @return result The result as a signed 59.18-decimal fixed-point number.
function gm(int256 x, int256 y) internal pure returns (int256 result) {
if (x == 0) {
return 0;
}
unchecked {
// Checking for overflow this way is faster than letting Solidity do it.
int256 xy = x * y;
if (xy / x != y) {
revert PRBMathSD59x18__GmOverflow(x, y);
}
// The product cannot be negative.
if (xy < 0) {
revert PRBMathSD59x18__GmNegativeProduct(x, y);
}
// We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE
// during multiplication. See the comments within the "sqrt" function.
result = int256(PRBMath.sqrt(uint256(xy)));
}
}
/// @notice Calculates 1 / x, rounding toward zero.
///
/// @dev Requirements:
/// - x cannot be zero.
///
/// @param x The signed 59.18-decimal fixed-point number for which to calculate the inverse.
/// @return result The inverse as a signed 59.18-decimal fixed-point number.
function inv(int256 x) internal pure returns (int256 result) {
unchecked {
// 1e36 is SCALE * SCALE.
result = 1e36 / x;
}
}
/// @notice Calculates the natural logarithm of x.
///
/// @dev Based on the insight that ln(x) = log2(x) / log2(e).
///
/// Requirements:
/// - All from "log2".
///
/// Caveats:
/// - All from "log2".
/// - This doesn't return exactly 1 for 2718281828459045235, for that we would need more fine-grained precision.
///
/// @param x The signed 59.18-decimal fixed-point number for which to calculate the natural logarithm.
/// @return result The natural logarithm as a signed 59.18-decimal fixed-point number.
function ln(int256 x) internal pure returns (int256 result) {
// Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)
// can return is 195205294292027477728.
unchecked {
result = (log2(x) * SCALE) / LOG2_E;
}
}
/// @notice Calculates the common logarithm of x.
///
/// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common
/// logarithm based on the insight that log10(x) = log2(x) / log2(10).
///
/// Requirements:
/// - All from "log2".
///
/// Caveats:
/// - All from "log2".
///
/// @param x The signed 59.18-decimal fixed-point number for which to calculate the common logarithm.
/// @return result The common logarithm as a signed 59.18-decimal fixed-point number.
function log10(int256 x) internal pure returns (int256 result) {
if (x <= 0) {
revert PRBMathSD59x18__LogInputTooSmall(x);
}
// Note that the "mul" in this block is the assembly mul operation, not the "mul" function defined in this contract.
// prettier-ignore
assembly {
switch x
case 1 { result := mul(SCALE, sub(0, 18)) }
case 10 { result := mul(SCALE, sub(1, 18)) }
case 100 { result := mul(SCALE, sub(2, 18)) }
case 1000 { result := mul(SCALE, sub(3, 18)) }
case 10000 { result := mul(SCALE, sub(4, 18)) }
case 100000 { result := mul(SCALE, sub(5, 18)) }
case 1000000 { result := mul(SCALE, sub(6, 18)) }
case 10000000 { result := mul(SCALE, sub(7, 18)) }
case 100000000 { result := mul(SCALE, sub(8, 18)) }
case 1000000000 { result := mul(SCALE, sub(9, 18)) }
case 10000000000 { result := mul(SCALE, sub(10, 18)) }
case 100000000000 { result := mul(SCALE, sub(11, 18)) }
case 1000000000000 { result := mul(SCALE, sub(12, 18)) }
case 10000000000000 { result := mul(SCALE, sub(13, 18)) }
case 100000000000000 { result := mul(SCALE, sub(14, 18)) }
case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }
case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }
case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := SCALE }
case 100000000000000000000 { result := mul(SCALE, 2) }
case 1000000000000000000000 { result := mul(SCALE, 3) }
case 10000000000000000000000 { result := mul(SCALE, 4) }
case 100000000000000000000000 { result := mul(SCALE, 5) }
case 1000000000000000000000000 { result := mul(SCALE, 6) }
case 10000000000000000000000000 { result := mul(SCALE, 7) }
case 100000000000000000000000000 { result := mul(SCALE, 8) }
case 1000000000000000000000000000 { result := mul(SCALE, 9) }
case 10000000000000000000000000000 { result := mul(SCALE, 10) }
case 100000000000000000000000000000 { result := mul(SCALE, 11) }
case 1000000000000000000000000000000 { result := mul(SCALE, 12) }
case 10000000000000000000000000000000 { result := mul(SCALE, 13) }
case 100000000000000000000000000000000 { result := mul(SCALE, 14) }
case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }
case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }
case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }
case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }
case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }
case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }
case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }
case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }
case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }
default {
result := MAX_SD59x18
}
}
if (result == MAX_SD59x18) {
// Do the fixed-point division inline to save gas. The denominator is log2(10).
unchecked {
result = (log2(x) * SCALE) / 3_321928094887362347;
}
}
}
/// @notice Calculates the binary logarithm of x.
///
/// @dev Based on the iterative approximation algorithm.
/// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
///
/// Requirements:
/// - x must be greater than zero.
///
/// Caveats:
/// - The results are not perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.
///
/// @param x The signed 59.18-decimal fixed-point number for which to calculate the binary logarithm.
/// @return result The binary logarithm as a signed 59.18-decimal fixed-point number.
function log2(int256 x) internal pure returns (int256 result) {
if (x <= 0) {
revert PRBMathSD59x18__LogInputTooSmall(x);
}
unchecked {
// This works because log2(x) = -log2(1/x).
int256 sign;
if (x >= SCALE) {
sign = 1;
} else {
sign = -1;
// Do the fixed-point inversion inline to save gas. The numerator is SCALE * SCALE.
assembly {
x := div(1000000000000000000000000000000000000, x)
}
}
// Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).
uint256 n = PRBMath.mostSignificantBit(uint256(x / SCALE));
// The integer part of the logarithm as a signed 59.18-decimal fixed-point number. The operation can't overflow
// because n is maximum 255, SCALE is 1e18 and sign is either 1 or -1.
result = int256(n) * SCALE;
// This is y = x * 2^(-n).
int256 y = x >> n;
// If y = 1, the fractional part is zero.
if (y == SCALE) {
return result * sign;
}
// Calculate the fractional part via the iterative approximation.
// The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster.
for (int256 delta = int256(HALF_SCALE); delta > 0; delta >>= 1) {
y = (y * y) / SCALE;
// Is y^2 > 2 and so in the range [2,4)?
if (y >= 2 * SCALE) {
// Add the 2^(-m) factor to the logarithm.
result += delta;
// Corresponds to z/2 on Wikipedia.
y >>= 1;
}
}
result *= sign;
}
}
/// @notice Multiplies two signed 59.18-decimal fixed-point numbers together, returning a new signed 59.18-decimal
/// fixed-point number.
///
/// @dev Variant of "mulDiv" that works with signed numbers and employs constant folding, i.e. the denominator is
/// always 1e18.
///
/// Requirements:
/// - All from "PRBMath.mulDivFixedPoint".
/// - None of the inputs can be MIN_SD59x18
/// - The result must fit within MAX_SD59x18.
///
/// Caveats:
/// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
///
/// @param x The multiplicand as a signed 59.18-decimal fixed-point number.
/// @param y The multiplier as a signed 59.18-decimal fixed-point number.
/// @return result The product as a signed 59.18-decimal fixed-point number.
function mul(int256 x, int256 y) internal pure returns (int256 result) {
if (x == MIN_SD59x18 || y == MIN_SD59x18) {
revert PRBMathSD59x18__MulInputTooSmall();
}
unchecked {
uint256 ax;
uint256 ay;
ax = x < 0 ? uint256(-x) : uint256(x);
ay = y < 0 ? uint256(-y) : uint256(y);
uint256 rAbs = PRBMath.mulDivFixedPoint(ax, ay);
if (rAbs > uint256(MAX_SD59x18)) {
revert PRBMathSD59x18__MulOverflow(rAbs);
}
uint256 sx;
uint256 sy;
assembly {
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
}
result = sx ^ sy == 1 ? -int256(rAbs) : int256(rAbs);
}
}
/// @notice Returns PI as a signed 59.18-decimal fixed-point number.
function pi() internal pure returns (int256 result) {
result = 3_141592653589793238;
}
/// @notice Raises x to the power of y.
///
/// @dev Based on the insight that x^y = 2^(log2(x) * y).
///
/// Requirements:
/// - All from "exp2", "log2" and "mul".
/// - z cannot be zero.
///
/// Caveats:
/// - All from "exp2", "log2" and "mul".
/// - Assumes 0^0 is 1.
///
/// @param x Number to raise to given power y, as a signed 59.18-decimal fixed-point number.
/// @param y Exponent to raise x to, as a signed 59.18-decimal fixed-point number.
/// @return result x raised to power y, as a signed 59.18-decimal fixed-point number.
function pow(int256 x, int256 y) internal pure returns (int256 result) {
if (x == 0) {
result = y == 0 ? SCALE : int256(0);
} else {
result = exp2(mul(log2(x), y));
}
}
/// @notice Raises x (signed 59.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the
/// famous algorithm "exponentiation by squaring".
///
/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring
///
/// Requirements:
/// - All from "abs" and "PRBMath.mulDivFixedPoint".
/// - The result must fit within MAX_SD59x18.
///
/// Caveats:
/// - All from "PRBMath.mulDivFixedPoint".
/// - Assumes 0^0 is 1.
///
/// @param x The base as a signed 59.18-decimal fixed-point number.
/// @param y The exponent as an uint256.
/// @return result The result as a signed 59.18-decimal fixed-point number.
function powu(int256 x, uint256 y) internal pure returns (int256 result) {
uint256 xAbs = uint256(abs(x));
// Calculate the first iteration of the loop in advance.
uint256 rAbs = y & 1 > 0 ? xAbs : uint256(SCALE);
// Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster.
uint256 yAux = y;
for (yAux >>= 1; yAux > 0; yAux >>= 1) {
xAbs = PRBMath.mulDivFixedPoint(xAbs, xAbs);
// Equivalent to "y % 2 == 1" but faster.
if (yAux & 1 > 0) {
rAbs = PRBMath.mulDivFixedPoint(rAbs, xAbs);
}
}
// The result must fit within the 59.18-decimal fixed-point representation.
if (rAbs > uint256(MAX_SD59x18)) {
revert PRBMathSD59x18__PowuOverflow(rAbs);
}
// Is the base negative and the exponent an odd number?
bool isNegative = x < 0 && y & 1 == 1;
result = isNegative ? -int256(rAbs) : int256(rAbs);
}
/// @notice Returns 1 as a signed 59.18-decimal fixed-point number.
function scale() internal pure returns (int256 result) {
result = SCALE;
}
/// @notice Calculates the square root of x, rounding down.
/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Requirements:
/// - x cannot be negative.
/// - x must be less than MAX_SD59x18 / SCALE.
///
/// @param x The signed 59.18-decimal fixed-point number for which to calculate the square root.
/// @return result The result as a signed 59.18-decimal fixed-point .
function sqrt(int256 x) internal pure returns (int256 result) {
unchecked {
if (x < 0) {
revert PRBMathSD59x18__SqrtNegativeInput(x);
}
if (x > MAX_SD59x18 / SCALE) {
revert PRBMathSD59x18__SqrtOverflow(x);
}
// Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two signed
// 59.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).
result = int256(PRBMath.sqrt(uint256(x * SCALE)));
}
}
/// @notice Converts a signed 59.18-decimal fixed-point number to basic integer form, rounding down in the process.
/// @param x The signed 59.18-decimal fixed-point number to convert.
/// @return result The same number in basic integer form.
function toInt(int256 x) internal pure returns (int256 result) {
unchecked {
result = x / SCALE;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721URIStorage.sol)
pragma solidity ^0.8.0;
import "../ERC721.sol";
/**
* @dev ERC721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is ERC721 {
using Strings for uint256;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721URIStorage: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked).
if (bytes(_tokenURI).length > 0) {
return string(abi.encodePacked(base, _tokenURI));
}
return super.tokenURI(tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
require(_exists(tokenId), "ERC721URIStorage: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual override {
super._burn(tokenId);
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/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() {
_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
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^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() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
pragma solidity ^0.8.0;
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
*/
library Counters {
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;
/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);
/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);
/// @notice Emitted when one of the inputs is type(int256).min.
error PRBMath__MulDivSignedInputTooSmall();
/// @notice Emitted when the intermediary absolute result overflows int256.
error PRBMath__MulDivSignedOverflow(uint256 rAbs);
/// @notice Emitted when the input is MIN_SD59x18.
error PRBMathSD59x18__AbsInputTooSmall();
/// @notice Emitted when ceiling a number overflows SD59x18.
error PRBMathSD59x18__CeilOverflow(int256 x);
/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__DivInputTooSmall();
/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.
error PRBMathSD59x18__DivOverflow(uint256 rAbs);
/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathSD59x18__ExpInputTooBig(int256 x);
/// @notice Emitted when the input is greater than 192.
error PRBMathSD59x18__Exp2InputTooBig(int256 x);
/// @notice Emitted when flooring a number underflows SD59x18.
error PRBMathSD59x18__FloorUnderflow(int256 x);
/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMathSD59x18__FromIntOverflow(int256 x);
/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMathSD59x18__FromIntUnderflow(int256 x);
/// @notice Emitted when the product of the inputs is negative.
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);
/// @notice Emitted when multiplying the inputs overflows SD59x18.
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);
/// @notice Emitted when the input is less than or equal to zero.
error PRBMathSD59x18__LogInputTooSmall(int256 x);
/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__MulInputTooSmall();
/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__MulOverflow(uint256 rAbs);
/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);
/// @notice Emitted when the input is negative.
error PRBMathSD59x18__SqrtNegativeInput(int256 x);
/// @notice Emitted when the calculating the square root overflows SD59x18.
error PRBMathSD59x18__SqrtOverflow(int256 x);
/// @notice Emitted when addition overflows UD60x18.
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);
/// @notice Emitted when ceiling a number overflows UD60x18.
error PRBMathUD60x18__CeilOverflow(uint256 x);
/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathUD60x18__ExpInputTooBig(uint256 x);
/// @notice Emitted when the input is greater than 192.
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);
/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.
error PRBMathUD60x18__FromUintOverflow(uint256 x);
/// @notice Emitted when multiplying the inputs overflows UD60x18.
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);
/// @notice Emitted when the input is less than 1.
error PRBMathUD60x18__LogInputTooSmall(uint256 x);
/// @notice Emitted when the calculating the square root overflows UD60x18.
error PRBMathUD60x18__SqrtOverflow(uint256 x);
/// @notice Emitted when subtraction underflows UD60x18.
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);
/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library
/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point
/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.
library PRBMath {
/// STRUCTS ///
struct SD59x18 {
int256 value;
}
struct UD60x18 {
uint256 value;
}
/// STORAGE ///
/// @dev How many trailing decimals can be represented.
uint256 internal constant SCALE = 1e18;
/// @dev Largest power of two divisor of SCALE.
uint256 internal constant SCALE_LPOTD = 262144;
/// @dev SCALE inverted mod 2^256.
uint256 internal constant SCALE_INVERSE =
78156646155174841979727994598816262306175212592076161876661_508869554232690281;
/// FUNCTIONS ///
/// @notice Calculates the binary exponent of x using the binary fraction method.
/// @dev Has to use 192.64-bit fixed-point numbers.
/// See https://ethereum.stackexchange.com/a/96594/24693.
/// @param x The exponent as an unsigned 192.64-bit fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
function exp2(uint256 x) internal pure returns (uint256 result) {
unchecked {
// Start from 0.5 in the 192.64-bit fixed-point format.
result = 0x800000000000000000000000000000000000000000000000;
// Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
// because the initial result is 2^191 and all magic factors are less than 2^65.
if (x & 0x8000000000000000 > 0) {
result = (result * 0x16A09E667F3BCC909) >> 64;
}
if (x & 0x4000000000000000 > 0) {
result = (result * 0x1306FE0A31B7152DF) >> 64;
}
if (x & 0x2000000000000000 > 0) {
result = (result * 0x1172B83C7D517ADCE) >> 64;
}
if (x & 0x1000000000000000 > 0) {
result = (result * 0x10B5586CF9890F62A) >> 64;
}
if (x & 0x800000000000000 > 0) {
result = (result * 0x1059B0D31585743AE) >> 64;
}
if (x & 0x400000000000000 > 0) {
result = (result * 0x102C9A3E778060EE7) >> 64;
}
if (x & 0x200000000000000 > 0) {
result = (result * 0x10163DA9FB33356D8) >> 64;
}
if (x & 0x100000000000000 > 0) {
result = (result * 0x100B1AFA5ABCBED61) >> 64;
}
if (x & 0x80000000000000 > 0) {
result = (result * 0x10058C86DA1C09EA2) >> 64;
}
if (x & 0x40000000000000 > 0) {
result = (result * 0x1002C605E2E8CEC50) >> 64;
}
if (x & 0x20000000000000 > 0) {
result = (result * 0x100162F3904051FA1) >> 64;
}
if (x & 0x10000000000000 > 0) {
result = (result * 0x1000B175EFFDC76BA) >> 64;
}
if (x & 0x8000000000000 > 0) {
result = (result * 0x100058BA01FB9F96D) >> 64;
}
if (x & 0x4000000000000 > 0) {
result = (result * 0x10002C5CC37DA9492) >> 64;
}
if (x & 0x2000000000000 > 0) {
result = (result * 0x1000162E525EE0547) >> 64;
}
if (x & 0x1000000000000 > 0) {
result = (result * 0x10000B17255775C04) >> 64;
}
if (x & 0x800000000000 > 0) {
result = (result * 0x1000058B91B5BC9AE) >> 64;
}
if (x & 0x400000000000 > 0) {
result = (result * 0x100002C5C89D5EC6D) >> 64;
}
if (x & 0x200000000000 > 0) {
result = (result * 0x10000162E43F4F831) >> 64;
}
if (x & 0x100000000000 > 0) {
result = (result * 0x100000B1721BCFC9A) >> 64;
}
if (x & 0x80000000000 > 0) {
result = (result * 0x10000058B90CF1E6E) >> 64;
}
if (x & 0x40000000000 > 0) {
result = (result * 0x1000002C5C863B73F) >> 64;
}
if (x & 0x20000000000 > 0) {
result = (result * 0x100000162E430E5A2) >> 64;
}
if (x & 0x10000000000 > 0) {
result = (result * 0x1000000B172183551) >> 64;
}
if (x & 0x8000000000 > 0) {
result = (result * 0x100000058B90C0B49) >> 64;
}
if (x & 0x4000000000 > 0) {
result = (result * 0x10000002C5C8601CC) >> 64;
}
if (x & 0x2000000000 > 0) {
result = (result * 0x1000000162E42FFF0) >> 64;
}
if (x & 0x1000000000 > 0) {
result = (result * 0x10000000B17217FBB) >> 64;
}
if (x & 0x800000000 > 0) {
result = (result * 0x1000000058B90BFCE) >> 64;
}
if (x & 0x400000000 > 0) {
result = (result * 0x100000002C5C85FE3) >> 64;
}
if (x & 0x200000000 > 0) {
result = (result * 0x10000000162E42FF1) >> 64;
}
if (x & 0x100000000 > 0) {
result = (result * 0x100000000B17217F8) >> 64;
}
if (x & 0x80000000 > 0) {
result = (result * 0x10000000058B90BFC) >> 64;
}
if (x & 0x40000000 > 0) {
result = (result * 0x1000000002C5C85FE) >> 64;
}
if (x & 0x20000000 > 0) {
result = (result * 0x100000000162E42FF) >> 64;
}
if (x & 0x10000000 > 0) {
result = (result * 0x1000000000B17217F) >> 64;
}
if (x & 0x8000000 > 0) {
result = (result * 0x100000000058B90C0) >> 64;
}
if (x & 0x4000000 > 0) {
result = (result * 0x10000000002C5C860) >> 64;
}
if (x & 0x2000000 > 0) {
result = (result * 0x1000000000162E430) >> 64;
}
if (x & 0x1000000 > 0) {
result = (result * 0x10000000000B17218) >> 64;
}
if (x & 0x800000 > 0) {
result = (result * 0x1000000000058B90C) >> 64;
}
if (x & 0x400000 > 0) {
result = (result * 0x100000000002C5C86) >> 64;
}
if (x & 0x200000 > 0) {
result = (result * 0x10000000000162E43) >> 64;
}
if (x & 0x100000 > 0) {
result = (result * 0x100000000000B1721) >> 64;
}
if (x & 0x80000 > 0) {
result = (result * 0x10000000000058B91) >> 64;
}
if (x & 0x40000 > 0) {
result = (result * 0x1000000000002C5C8) >> 64;
}
if (x & 0x20000 > 0) {
result = (result * 0x100000000000162E4) >> 64;
}
if (x & 0x10000 > 0) {
result = (result * 0x1000000000000B172) >> 64;
}
if (x & 0x8000 > 0) {
result = (result * 0x100000000000058B9) >> 64;
}
if (x & 0x4000 > 0) {
result = (result * 0x10000000000002C5D) >> 64;
}
if (x & 0x2000 > 0) {
result = (result * 0x1000000000000162E) >> 64;
}
if (x & 0x1000 > 0) {
result = (result * 0x10000000000000B17) >> 64;
}
if (x & 0x800 > 0) {
result = (result * 0x1000000000000058C) >> 64;
}
if (x & 0x400 > 0) {
result = (result * 0x100000000000002C6) >> 64;
}
if (x & 0x200 > 0) {
result = (result * 0x10000000000000163) >> 64;
}
if (x & 0x100 > 0) {
result = (result * 0x100000000000000B1) >> 64;
}
if (x & 0x80 > 0) {
result = (result * 0x10000000000000059) >> 64;
}
if (x & 0x40 > 0) {
result = (result * 0x1000000000000002C) >> 64;
}
if (x & 0x20 > 0) {
result = (result * 0x10000000000000016) >> 64;
}
if (x & 0x10 > 0) {
result = (result * 0x1000000000000000B) >> 64;
}
if (x & 0x8 > 0) {
result = (result * 0x10000000000000006) >> 64;
}
if (x & 0x4 > 0) {
result = (result * 0x10000000000000003) >> 64;
}
if (x & 0x2 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
if (x & 0x1 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
// We're doing two things at the same time:
//
// 1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
// the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
// rather than 192.
// 2. Convert the result to the unsigned 60.18-decimal fixed-point format.
//
// This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
result *= SCALE;
result >>= (191 - (x >> 64));
}
}
/// @notice Finds the zero-based index of the first one in the binary representation of x.
/// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
/// @param x The uint256 number for which to find the index of the most significant bit.
/// @return msb The index of the most significant bit as an uint256.
function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
if (x >= 2**128) {
x >>= 128;
msb += 128;
}
if (x >= 2**64) {
x >>= 64;
msb += 64;
}
if (x >= 2**32) {
x >>= 32;
msb += 32;
}
if (x >= 2**16) {
x >>= 16;
msb += 16;
}
if (x >= 2**8) {
x >>= 8;
msb += 8;
}
if (x >= 2**4) {
x >>= 4;
msb += 4;
}
if (x >= 2**2) {
x >>= 2;
msb += 2;
}
if (x >= 2**1) {
// No need to shift x any more.
msb += 1;
}
}
/// @notice Calculates floor(x*y÷denominator) with full precision.
///
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
///
/// Requirements:
/// - The denominator cannot be zero.
/// - The result must fit within uint256.
///
/// Caveats:
/// - This function does not work with fixed-point numbers.
///
/// @param x The multiplicand as an uint256.
/// @param y The multiplier as an uint256.
/// @param denominator The divisor as an uint256.
/// @return result The result as an uint256.
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
unchecked {
result = prod0 / denominator;
}
return result;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (prod1 >= denominator) {
revert PRBMath__MulDivOverflow(prod1, denominator);
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
unchecked {
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 lpotdod = denominator & (~denominator + 1);
assembly {
// Divide denominator by lpotdod.
denominator := div(denominator, lpotdod)
// Divide [prod1 prod0] by lpotdod.
prod0 := div(prod0, lpotdod)
// Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * lpotdod;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/// @notice Calculates floor(x*y÷1e18) with full precision.
///
/// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the
/// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of
/// being rounded to 1e-18. See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
///
/// Requirements:
/// - The result must fit within uint256.
///
/// Caveats:
/// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
/// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:
/// 1. x * y = type(uint256).max * SCALE
/// 2. (x * y) % SCALE >= SCALE / 2
///
/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
/// @return result The result as an unsigned 60.18-decimal fixed-point number.
function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 >= SCALE) {
revert PRBMath__MulDivFixedPointOverflow(prod1);
}
uint256 remainder;
uint256 roundUpUnit;
assembly {
remainder := mulmod(x, y, SCALE)
roundUpUnit := gt(remainder, 499999999999999999)
}
if (prod1 == 0) {
unchecked {
result = (prod0 / SCALE) + roundUpUnit;
return result;
}
}
assembly {
result := add(
mul(
or(
div(sub(prod0, remainder), SCALE_LPOTD),
mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
),
SCALE_INVERSE
),
roundUpUnit
)
}
}
/// @notice Calculates floor(x*y÷denominator) with full precision.
///
/// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately.
///
/// Requirements:
/// - None of the inputs can be type(int256).min.
/// - The result must fit within int256.
///
/// @param x The multiplicand as an int256.
/// @param y The multiplier as an int256.
/// @param denominator The divisor as an int256.
/// @return result The result as an int256.
function mulDivSigned(
int256 x,
int256 y,
int256 denominator
) internal pure returns (int256 result) {
if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
revert PRBMath__MulDivSignedInputTooSmall();
}
// Get hold of the absolute values of x, y and the denominator.
uint256 ax;
uint256 ay;
uint256 ad;
unchecked {
ax = x < 0 ? uint256(-x) : uint256(x);
ay = y < 0 ? uint256(-y) : uint256(y);
ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
}
// Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
uint256 rAbs = mulDiv(ax, ay, ad);
if (rAbs > uint256(type(int256).max)) {
revert PRBMath__MulDivSignedOverflow(rAbs);
}
// Get the signs of x, y and the denominator.
uint256 sx;
uint256 sy;
uint256 sd;
assembly {
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
sd := sgt(denominator, sub(0, 1))
}
// XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.
// If yes, the result should be negative.
result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
}
/// @notice Calculates the square root of x, rounding down.
/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
///
/// Caveats:
/// - This function does not work with fixed-point numbers.
///
/// @param x The uint256 number for which to calculate the square root.
/// @return result The result as an uint256.
function sqrt(uint256 x) internal pure returns (uint256 result) {
if (x == 0) {
return 0;
}
// Set the initial guess to the least power of two that is greater than or equal to sqrt(x).
uint256 xAux = uint256(x);
result = 1;
if (xAux >= 0x100000000000000000000000000000000) {
xAux >>= 128;
result <<= 64;
}
if (xAux >= 0x10000000000000000) {
xAux >>= 64;
result <<= 32;
}
if (xAux >= 0x100000000) {
xAux >>= 32;
result <<= 16;
}
if (xAux >= 0x10000) {
xAux >>= 16;
result <<= 8;
}
if (xAux >= 0x100) {
xAux >>= 8;
result <<= 4;
}
if (xAux >= 0x10) {
xAux >>= 4;
result <<= 2;
}
if (xAux >= 0x8) {
result <<= 1;
}
// The operations can never overflow because the result is max 2^127 when it enters this block.
unchecked {
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1; // Seven iterations should be enough
uint256 roundedDownResult = x / result;
return result >= roundedDownResult ? roundedDownResult : result;
}
}
}{
"optimizer": {
"enabled": true,
"runs": 2266
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_buddyCoreAddr","type":"address"},{"internalType":"address","name":"_gooContractAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"PRBMathSD59x18__AbsInputTooSmall","type":"error"},{"inputs":[],"name":"PRBMathSD59x18__DivInputTooSmall","type":"error"},{"inputs":[{"internalType":"uint256","name":"rAbs","type":"uint256"}],"name":"PRBMathSD59x18__DivOverflow","type":"error"},{"inputs":[{"internalType":"int256","name":"x","type":"int256"}],"name":"PRBMathSD59x18__LogInputTooSmall","type":"error"},{"inputs":[{"internalType":"uint256","name":"rAbs","type":"uint256"}],"name":"PRBMathSD59x18__PowuOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"}],"name":"PRBMath__MulDivFixedPointOverflow","type":"error"},{"inputs":[{"internalType":"uint256","name":"prod1","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"PRBMath__MulDivOverflow","type":"error"},{"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":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EggFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"owner","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Feed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"eggId1","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"eggId2","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"eggId3","type":"uint256"}],"name":"Fuse","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"newLevel","type":"uint256"}],"name":"Upgrade","type":"event"},{"inputs":[],"name":"BASE_URI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"bearOwnerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bears","outputs":[{"internalType":"enum ERC721Full.DNA","name":"dna","type":"uint8"},{"internalType":"uint256","name":"fed","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buddyContract","outputs":[{"internalType":"contract IBuddyCore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cost3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"wbid","type":"uint256"}],"name":"eggBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"wbid","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"eggOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"mbids","type":"uint256[]"},{"internalType":"uint256","name":"wbid","type":"uint256"}],"name":"feed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"mbids","type":"uint256[]"},{"internalType":"uint256","name":"eggId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"feedEgg","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"eggId1","type":"uint256"},{"internalType":"uint256","name":"eggId2","type":"uint256"}],"name":"fuse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ERC721Full.DNA","name":"_DNA","type":"uint8"}],"name":"getBaseMaxLevel","outputs":[{"internalType":"uint16","name":"maxLevel","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ERC721Full.DNA","name":"_DNA","type":"uint8"}],"name":"getCost","outputs":[{"internalType":"uint256","name":"GOO","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getEgg","outputs":[{"internalType":"enum ERC721Full.DNA","name":"","type":"uint8"},{"internalType":"enum ERC721Full.RARITY","name":"","type":"uint8"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ERC721Full.DNA","name":"dna","type":"uint8"},{"internalType":"uint256","name":"level","type":"uint256"}],"name":"getGOOForLevel","outputs":[{"internalType":"uint256","name":"gooForLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ERC721Full.DNA","name":"dna","type":"uint8"},{"internalType":"uint256","name":"level","type":"uint256"}],"name":"getGOOToLevel","outputs":[{"internalType":"uint256","name":"gooToLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"getHatcheryCost","outputs":[{"internalType":"uint256","name":"cost","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"},{"internalType":"uint256","name":"GOO","type":"uint256"}],"name":"getLevel","outputs":[{"internalType":"uint16","name":"level","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"}],"name":"getMaxLevel","outputs":[{"internalType":"uint256","name":"maxLevel","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"wbid","type":"uint256"}],"name":"getTokensByParent","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"goo","outputs":[{"internalType":"contract IGoo","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hatchery","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatcheryCost0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatcheryCost1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatcheryCost2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatcheryCost3","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatcheryCost4","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"isOperator","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxHatchery","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLevel0","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLevel1","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLevel2","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLevel3","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"id","type":"uint256"},{"internalType":"enum ERC721Full.DNA","name":"_DNA","type":"uint8"},{"internalType":"address","name":"_owner","type":"address"}],"name":"setBear","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"enum ERC721Full.DNA[]","name":"DNAs","type":"uint8[]"},{"internalType":"address[]","name":"owners","type":"address[]"}],"name":"setBears","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_buddyCoreAddr","type":"address"}],"name":"setBuddyContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cost0","type":"uint256"},{"internalType":"uint256","name":"_cost1","type":"uint256"},{"internalType":"uint256","name":"_cost2","type":"uint256"},{"internalType":"uint256","name":"_cost3","type":"uint256"}],"name":"setCosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gooContractAddr","type":"address"}],"name":"setGooContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_hatcheryCost0","type":"uint256"},{"internalType":"uint256","name":"_hatcheryCost1","type":"uint256"},{"internalType":"uint256","name":"_hatcheryCost2","type":"uint256"},{"internalType":"uint256","name":"_hatcheryCost3","type":"uint256"},{"internalType":"uint256","name":"_hatcheryCost4","type":"uint256"}],"name":"setHatcheryCosts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxHatchery","type":"uint256"}],"name":"setMaxHatchery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_maxLevel0","type":"uint16"},{"internalType":"uint16","name":"_maxLevel1","type":"uint16"},{"internalType":"uint16","name":"_maxLevel2","type":"uint16"},{"internalType":"uint16","name":"_maxLevel3","type":"uint16"}],"name":"setMaxLevels","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":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"mbids","type":"uint256[]"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c0604052601c60809081527f68747470733a2f2f6170692e6d6963726f627564646965732e696f2f0000000060a052600e906200003e90826200028b565b50620186a0601755620249f060185562030d406019556203d090601a819055601b80546001600160401b031916663200280023001e1790556005601c5561c350601d55601e55620f4240601f55624c4b406020556302faf080602155348015620000a757600080fd5b506040516200638538038062006385833981016040819052620000ca9162000374565b6040518060400160405280601781526020017f5761746572204265617220474f4f20426162792045676700000000000000000081525060405180604001604052806005815260200164574247424560d81b81525081600090816200012f91906200028b565b5060016200013e82826200028b565b5050600b805460ff191690555062000156336200018c565b601280546001600160a01b039384166001600160a01b0319918216179091556013805492909316911617905542601655620003ac565b600b80546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200021157607f821691505b6020821081036200023257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200028657600081815260208120601f850160051c81016020861015620002615750805b601f850160051c820191505b8181101562000282578281556001016200026d565b5050505b505050565b81516001600160401b03811115620002a757620002a7620001e6565b620002bf81620002b88454620001fc565b8462000238565b602080601f831160018114620002f75760008415620002de5750858301515b600019600386901b1c1916600185901b17855562000282565b600085815260208120601f198616915b82811015620003285788860151825594840194600190910190840162000307565b5085821015620003475787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b03811681146200036f57600080fd5b919050565b600080604083850312156200038857600080fd5b620003938362000357565b9150620003a36020840162000357565b90509250929050565b615fc980620003bc6000396000f3fe608060405234801561001057600080fd5b50600436106104205760003560e01c8063666fa18611610235578063b423156311610135578063e994193b116100c8578063ed3cad1f11610097578063f2fde38b1161007c578063f2fde38b146108e5578063f68858e4146108f8578063feb40f7e1461090b57600080fd5b8063ed3cad1f146108bc578063f17aaf0c146108d257600080fd5b8063e994193b1461087a578063eaafba131461088d578063eb27def6146108a0578063ec0e262b146108b357600080fd5b8063c87b56dd11610104578063c87b56dd14610839578063cd58863f1461084c578063dbddb26a1461085f578063e985e9c51461086757600080fd5b8063b4231563146107b4578063b88d4fde146107ff578063c00bb57814610812578063c3bc86b91461082557600080fd5b80638da5cb5b116101c85780639a1b288511610197578063a22cb4651161017c578063a22cb4651461077b578063a4d225351461078e578063b25ec0b8146107a157600080fd5b80639a1b288514610769578063a1c1c1921461077257600080fd5b80638da5cb5b1461072f578063937113ac1461074557806394f568dd1461074e57806395d89b411461076157600080fd5b806378a3b9801161020457806378a3b980146106ee5780638147e01e146107015780638456cb59146107145780638784fde81461071c57600080fd5b8063666fa186146106b25780636d25571a146106ca57806370a08231146106d3578063715018a6146106e657600080fd5b80633c7d702211610340578063560de6fe116102d357806362617b92116102a25780636389263a116102875780636389263a1461068d57806364c4b56d146106a05780636503b88e146106a957600080fd5b806362617b92146106675780636352211e1461067a57600080fd5b8063560de6fe1461062057806359c6f87a146106295780635bbaee671461063c5780635c975abb1461065c57600080fd5b80634d90769b1161030f5780634d90769b146105d45780634f6ccce7146105e757806354e957b4146105fa57806355f804b31461060d57600080fd5b80633c7d7022146105905780633f4ba83a1461059957806342842e0e146105a15780634540b8ae146105b457600080fd5b806318160ddd116103b85780632f745c59116103875780632f745c591461054e57806333573dc214610561578063375f2b961461056a57806338da342a1461057d57600080fd5b806318160ddd1461050057806323b872dd146105085780632688a3341461051b578063274cdd5c1461053b57600080fd5b8063095ea7b3116103f4578063095ea7b3146104ae5780630f800356146104c357806312f4b154146104d6578063151c8fc5146104ed57600080fd5b806282f1aa1461042557806301ffc9a71461044b57806306fdde031461046e578063081812fc14610483575b600080fd5b601b546104339061ffff1681565b60405161ffff90911681526020015b60405180910390f35b61045e610459366004615443565b610976565b6040519015158152602001610442565b610476610987565b60405161044291906154b0565b6104966104913660046154c3565b610a19565b6040516001600160a01b039091168152602001610442565b6104c16104bc3660046154f1565b610ac4565b005b6104c16104d1366004615569565b610ad2565b6104df60175481565b604051908152602001610442565b6104df6104fb3660046154c3565b610bf4565b6008546104df565b6104c16105163660046155ab565b610c99565b61052e6105293660046154c3565b610d25565b60405161044291906155ec565b601354610496906001600160a01b031681565b6104df61055c3660046154f1565b610def565b6104df60185481565b6104df61057836600461563f565b610e97565b6104c161058b3660046154c3565b610f51565b6104df60205481565b6104c1610fb6565b6104c16105af3660046155ab565b611020565b6104df6105c23660046154c3565b60009081526011602052604090205490565b6104c16105e236600461565a565b61103b565b6104df6105f53660046154c3565b6110ca565b6104df610608366004615677565b61116e565b6104c161061b366004615725565b6111e9565b6104df601d5481565b6104c161063736600461576e565b611255565b6104df61064a36600461565a565b60156020526000908152604090205481565b600b5460ff1661045e565b6104df6106753660046157ba565b611787565b6104966106883660046154c3565b611816565b6104df61069b3660046157ba565b6118a1565b6104df601f5481565b6104df601a5481565b601b54610433906601000000000000900461ffff1681565b6104df601c5481565b6104df6106e136600461565a565b6118e2565b6104c161197c565b6104c16106fc36600461565a565b6119e6565b601254610496906001600160a01b031681565b6104c1611a75565b6104c161072a3660046157d6565b611add565b600b5461010090046001600160a01b0316610496565b6104df60165481565b6104df61075c3660046154c3565b611bcd565b610476611c9c565b6104df60195481565b6104df601e5481565b6104c1610789366004615870565b611cab565b61049661079c3660046154c3565b611cb6565b6104c16107af3660046158ae565b611d25565b6107f06107c23660046154c3565b60146020526000908152604090208054600182015460029092015460ff90911691906001600160a01b031683565b60405161044293929190615914565b6104c161080d36600461593e565b611d99565b61043361082036600461563f565b611e27565b601b546104339062010000900461ffff1681565b6104766108473660046154c3565b611ed7565b6104c161085a3660046159d0565b612330565b610476612438565b61045e610875366004615a24565b6124c6565b6104c1610888366004615a52565b612531565b6104c161089b366004615aa3565b612b12565b6104336108ae366004615677565b612c42565b6104df60215481565b601b5461043390640100000000900461ffff1681565b6104c16108e0366004615ae3565b612da1565b6104c16108f336600461565a565b612e18565b6104c1610906366004615677565b612f00565b6109636109193660046154c3565b6000908152600f6020526040902080546001820154600283015460039093015460ff8084169561010085049091169461ffff62010000860481169564010000000090041693929091565b6040516104429796959493929190615b1e565b6000610981826135a7565b92915050565b60606000805461099690615b69565b80601f01602080910402602001604051908101604052809291908181526020018280546109c290615b69565b8015610a0f5780601f106109e457610100808354040283529160200191610a0f565b820191906000526020600020905b8154815290600101906020018083116109f257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610aa85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b610ace82826135fd565b5050565b600b5460ff1615610b185760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b33600090815260156020526040902054601c548110610b795760405162461bcd60e51b815260206004820152601560248201527f4861746368657279206973206d6178206c6576656c00000000000000000000006044820152606401610a9f565b6000610b8482610bf4565b9050610b91848483613729565b50336000908152601560205260408120805460019290610bb2908490615bb3565b90915550610bc39050826001615bb3565b60405133907f318d2be9b9a887c0d168715bd2f44017dafbb3360b14cdcc2a8c0086b4e2d15190600090a350505050565b600081600003610c1357601d5461098190670de0b6b3a7640000615bc6565b81600103610c3057601e5461098190670de0b6b3a7640000615bc6565b81600203610c4d57601f5461098190670de0b6b3a7640000615bc6565b81600303610c6a5760205461098190670de0b6b3a7640000615bc6565b610c75600383615bdd565b602154610c829190615bc6565b61098190670de0b6b3a7640000615bc6565b919050565b610ca33382613dc5565b610d155760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a9f565b610d20838383613dd1565b505050565b600081815260116020526040812054606091819003610d585760408051600080825260208201909252905b509392505050565b60008167ffffffffffffffff811115610d7357610d73615699565b604051908082528060200260200182016040528015610d9c578160200160208202803683370190505b50905060005b82811015610d50576000610db6868361116e565b905080838381518110610dcb57610dcb615bf0565b60209081029190910101525080610de181615c06565b915050610da2565b50919050565b6000610dfa836118e2565b8210610e6e5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610a9f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000816004811115610eab57610eab6158e0565b600003610ec75760175461098190670de0b6b3a7640000615bc6565b816004811115610ed957610ed96158e0565b600103610ef55760185461098190670de0b6b3a7640000615bc6565b816004811115610f0757610f076158e0565b600203610f235760195461098190670de0b6b3a7640000615bc6565b6003826004811115610f3757610f376158e0565b10610c9457601a5461098190670de0b6b3a7640000615bc6565b600b546001600160a01b03610100909104163314610fb15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601c55565b600b546001600160a01b036101009091041633146110165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b61101e613fb6565b565b610d2083838360405180602001604052806000815250611d99565b600b546001600160a01b0361010090910416331461109b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b6013805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006110d560085490565b82106111495760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610a9f565b6008828154811061115c5761115c615bf0565b90600052602060002001549050919050565b60008281526011602052604081205482106111cb5760405162461bcd60e51b815260206004820152601d60248201527f456767206f776e657220696e646578206f7574206f6620626f756e64730000006044820152606401610a9f565b50600091825260106020908152604080842092845291905290205490565b600b546001600160a01b036101009091041633146112495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b600e610ace8282615c6e565b600b5460ff161561129b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b60008181526014602052604080822081516060810190925280548493929190829060ff1660048111156112d0576112d06158e0565b60048111156112e1576112e16158e0565b8152600182015460208201526002909101546001600160a01b03908116604092830152908201519192501633146113495760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b82600061135582610d25565b905060005b815181101561154c576000600f600084848151811061137b5761137b615bf0565b602002602001015181526020019081526020016000206040518060e00160405290816000820160009054906101000a900460ff1660048111156113c0576113c06158e0565b60048111156113d1576113d16158e0565b81528154602090910190610100900460ff1660048111156113f4576113f46158e0565b6004811115611405576114056158e0565b8152815461ffff62010000820481166020840152640100000000909104166040820152600182015460608201526002820154608082015260039091015460a0909101529050600081602001516004811115611462576114626158e0565b1480156114725750838160c00151145b156115395760165442118015611498575062015180601654426114959190615bdd565b10155b806114c757508060a001516016541180156114c75750620151808160a001516016546114c49190615bdd565b10155b6115395760405162461bcd60e51b815260206004820152602c60248201527f42656172206e656564732074696d65206265666f726520737061776e696e672060448201527f616e6f74686572206567672100000000000000000000000000000000000000006064820152608401610a9f565b508061154481615c06565b91505061135a565b505b6016544211801561156e5750620151806016544261156c9190615bdd565b115b156115935762015180601660008282546115889190615bb3565b9091555061154e9050565b600085815260146020526040812080549091906115b29060ff16610e97565b905060006115c18a8a84613729565b9050808360010160008282546115d79190615bb3565b90915550600090506115e833614052565b90506116336040805160e08101909152806000815260200160008152602001600061ffff168152602001600061ffff1681526020016000815260200160008152602001600081525090565b600060208201528454819060ff166004811115611652576116526158e0565b90816004811115611665576116656158e0565b9052504260a082015260c081018a9052805161168090611e27565b61ffff1660608201526000828152600f602052604090208151815483929190829060ff191660018360048111156116b9576116b96158e0565b021790555060208201518154829061ff0019166101008360048111156116e1576116e16158e0565b021790555060408201518154606084015161ffff9081166401000000000265ffff00000000199190931662010000021665ffffffff000019909116171781556080820151600182015560a0820151600282015560c09091015160039091015561174a8a836140a8565b828a837fd08d1e82229a1d0f8cd0a1da06c35f597af0438b2690e2288fe64999b6df50a660405160405180910390a4505050505050505050505050565b6000806064670de0b6b3a764000061179e86610e97565b6117a89190615d44565b6117b29190615d44565b905060006118036117cb670e92596fd6290000866140ef565b6117dd90670de0b6b3a7640000615d72565b7fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b00006141e3565b61180d9083615d99565b95945050505050565b6000818152600260205260408120546001600160a01b0316806109815760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610a9f565b6000806064670de0b6b3a76400006118b886610e97565b6118c29190615d44565b6118cc9190615d44565b90506000611803670e92596fd6290000856140ef565b60006001600160a01b0382166119605760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610a9f565b506001600160a01b031660009081526003602052604090205490565b600b546001600160a01b036101009091041633146119dc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b61101e60006142f4565b600b546001600160a01b03610100909104163314611a465760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b6012805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600b546001600160a01b03610100909104163314611ad55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b61101e614365565b600b546001600160a01b03610100909104163314611b3d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b60005b85811015611bc457611bb2878783818110611b5d57611b5d615bf0565b90506020020135868684818110611b7657611b76615bf0565b9050602002016020810190611b8b919061563f565b858585818110611b9d57611b9d615bf0565b905060200201602081019061089b919061565a565b80611bbc81615c06565b915050611b40565b50505050505050565b6000818152600f6020526040808220815160e08101909252805483929190829060ff166004811115611c0157611c016158e0565b6004811115611c1257611c126158e0565b81528154602090910190610100900460ff166004811115611c3557611c356158e0565b6004811115611c4657611c466158e0565b8152815461ffff620100008204811660208401526401000000009091048116604083015260018301546060808401919091526002840154608084015260039093015460a090920191909152910151169392505050565b60606001805461099690615b69565b610ace3383836143e0565b600081815260146020526040808220815160608101909252805483929190829060ff166004811115611cea57611cea6158e0565b6004811115611cfb57611cfb6158e0565b8152600182015460208201526002909101546001600160a01b031660409182015201519392505050565b600b546001600160a01b03610100909104163314611d855760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601793909355601891909155601955601a55565b611da33383613dc5565b611e155760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a9f565b611e21848484846144ae565b50505050565b6000816004811115611e3b57611e3b6158e0565b600003611e4e575050601b5461ffff1690565b816004811115611e6057611e606158e0565b600103611e7a5750601b5462010000900461ffff16919050565b816004811115611e8c57611e8c6158e0565b600203611ea85750601b54640100000000900461ffff16919050565b6003826004811115611ebc57611ebc6158e0565b10610c94575050601b546601000000000000900461ffff1690565b6000818152600260205260409020546060906001600160a01b0316611f645760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610a9f565b6000611f6e614537565b6000848152600f6020526040808220815160e0810190925280549394509192909190829060ff166004811115611fa657611fa66158e0565b6004811115611fb757611fb76158e0565b81528154602090910190610100900460ff166004811115611fda57611fda6158e0565b6004811115611feb57611feb6158e0565b8152815461ffff62010000820481166020840152640100000000909104166040820152600182015460608201526002820154608082015260039091015460a09091015280519091506000906004811115612047576120476158e0565b9050600082602001516004811115612061576120616158e0565b604080518082018252600881527f7374616e646172640000000000000000000000000000000000000000000000006020808301919091528251808401909352600683527f636f6d6d6f6e0000000000000000000000000000000000000000000000000000908301529192506001849003612112576040518060400160405280600481526020017f736572660000000000000000000000000000000000000000000000000000000081525091506121dd565b83600203612157576040518060400160405280600981526020017f696e76697369626c65000000000000000000000000000000000000000000000081525091506121dd565b8360030361219c576040518060400160405280600381526020017f696365000000000000000000000000000000000000000000000000000000000081525091506121dd565b836004036121dd576040518060400160405280600481526020017f6461726b0000000000000000000000000000000000000000000000000000000081525091505b8260010361221f575060408051808201909152600481527f726172650000000000000000000000000000000000000000000000000000000060208201526122e1565b82600203612261575060408051808201909152600981527f6c6567656e64617279000000000000000000000000000000000000000000000060208201526122e1565b826003036122a3575060408051808201909152600781527f6578616c7465640000000000000000000000000000000000000000000000000060208201526122e1565b826004036122e1575060408051808201909152600681527f646976696e65000000000000000000000000000000000000000000000000000060208201525b60008651116122ff5760405180602001604052806000815250612324565b85828260405160200161231493929190615dc9565b6040516020818303038152906040525b98975050505050505050565b600b546001600160a01b036101009091041633146123905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601b805461ffff9586167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000909116176201000094861694909402939093177fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff16640100000000928516929092027fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff169190911766010000000000009190931602919091179055565b600e805461244590615b69565b80601f016020809104026020016040519081016040528092919081815260200182805461247190615b69565b80156124be5780601f10612493576101008083540402835291602001916124be565b820191906000526020600020905b8154815290600101906020018083116124a157829003601f168201915b505050505081565b60007fffffffffffffffffffffffffa77f8452f4c89103ed0a52795538f187129821526001600160a01b0383160161250057506001610981565b6001600160a01b0380841660009081526005602090815260408083209386168352929052205460ff165b9392505050565b600b5460ff16156125775760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b8161258181611816565b6001600160a01b0316336001600160a01b0316146125d05760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b6000838152600f60205260408120906125f184670de0b6b3a7640000615bc6565b905060006125fe86611bcd565b600184015484549192506000916126189060ff1684611787565b6126229190615bdd565b845490915062010000900461ffff168211801561263f5750600081115b61268b5760405162461bcd60e51b815260206004820152601d60248201527f456767206174206d6178206c6576656c212054727920667573696e672e0000006044820152606401610a9f565b6000805b89811015612a7d5760008b8b838181106126ab576126ab615bf0565b6012546040517f8363871000000000000000000000000000000000000000000000000000000000815260209290920293909301356004820181905293506000926001600160a01b03169150638363871090602401602060405180830381865afa15801561271c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127409190615e34565b9050336001600160a01b03821614806127ef57506012546040517ff658518a000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039091169063f658518a90602401602060405180830381865afa1580156127b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127da9190615e34565b6001600160a01b0316336001600160a01b0316145b61283b5760405162461bcd60e51b815260206004820152601960248201527f4e6f7420617070726f76656420746f207370656e6420474f4f000000000000006044820152606401610a9f565b6013546040517f9cc7f708000000000000000000000000000000000000000000000000000000008152600481018490526000916001600160a01b031690639cc7f70890602401602060405180830381865afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c29190615e51565b9050876128cf8287615bb3565b11156128e2576128df8589615bdd565b90505b856128ed8287615bb3565b1115612900576128fd8587615bdd565b90505b6012546040516323b872dd60e01b81526001600160a01b03848116600483015230602483015260448201869052909116906323b872dd90606401600060405180830381600087803b15801561295457600080fd5b505af1158015612968573d6000803e3d6000fd5b505060135460405163b390c0ab60e01b815260048101879052602481018590526001600160a01b03909116925063b390c0ab9150604401600060405180830381600087803b1580156129b957600080fd5b505af11580156129cd573d6000803e3d6000fd5b50506012546040516323b872dd60e01b81523060048201526001600160a01b0386811660248301526044820188905290911692506323b872dd9150606401600060405180830381600087803b158015612a2557600080fd5b505af1158015612a39573d6000803e3d6000fd5b505050508085612a499190615bb3565b94508585101580612a5a5750878510155b15612a6757505050612a7d565b5050508080612a7590615c06565b91505061268f565b50612a888882612c42565b855461ffff9190911662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff909116178555600185018054829190600090612ad4908490615bb3565b9091555050604051819089907f9bf12cd03cc3b97f3d2a6b9fc65dd54bd989e3b1e70b761b03dffb6054d26a3090600090a350505050505050505050565b600b546001600160a01b03610100909104163314612b725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b604080516060810182526000808252602082018190529181019190915280836004811115612ba257612ba26158e0565b90816004811115612bb557612bb56158e0565b9052506001600160a01b03821660408083019190915260008581526014602052208151815483929190829060ff19166001836004811115612bf857612bf86158e0565b0217905550602082015160018201556040909101516002909101805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0390921691909117905550505050565b6000828152600f6020526040808220815160e08101909252805483929190829060ff166004811115612c7657612c766158e0565b6004811115612c8757612c876158e0565b81528154602090910190610100900460ff166004811115612caa57612caa6158e0565b6004811115612cbb57612cbb6158e0565b8152815461ffff62010000820481166020840152640100000000909104166040820152600182015460608201526002820154608082015260039091015460a09091015290506000839003612d1457604001519050610981565b60006064612d258360000151610e97565b612d30906014615bc6565b612d3a9190615e6a565b9050600081858460800151612d4f9190615bb3565b612d599190615bb3565b90506000612d6782846141e3565b90506000612d8d612d7783614546565b612d88670e92596fd6290000614546565b6141e3565b9050612324670de0b6b3a764000082615d44565b600b546001600160a01b03610100909104163314612e015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601d94909455601e92909255601f55602055602155565b600b546001600160a01b03610100909104163314612e785760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b6001600160a01b038116612ef45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a9f565b612efd816142f4565b50565b600b5460ff1615612f465760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b81612f5081611816565b6001600160a01b0316336001600160a01b031614612f9f5760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b81612fa981611816565b6001600160a01b0316336001600160a01b031614612ff85760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b6000848152600f6020526040808220815160e081019092528054829060ff166004811115613028576130286158e0565b6004811115613039576130396158e0565b81528154602090910190610100900460ff16600481111561305c5761305c6158e0565b600481111561306d5761306d6158e0565b8152815461ffff620100008204811660208085019190915264010000000090920416604080840191909152600184015460608401526002840154608084015260039093015460a0909201919091526000878152600f909152818120825160e0810190935280549394509092829060ff1660048111156130ee576130ee6158e0565b60048111156130ff576130ff6158e0565b81528154602090910190610100900460ff166004811115613122576131226158e0565b6004811115613133576131336158e0565b8152815461ffff6201000082048116602080850191909152640100000000909204166040830152600183015460608301526002830154608083015260039092015460a0909101528101519091506004811115613191576131916158e0565b826020015160048111156131a7576131a76158e0565b146131f45760405162461bcd60e51b815260206004820152601d60248201527f45676773206d757374206265207468652073616d6520726172697479210000006044820152606401610a9f565b80516004811115613207576132076158e0565b8251600481111561321a5761321a6158e0565b146132675760405162461bcd60e51b815260206004820152601a60248201527f45676773206d757374206265207468652073616d6520444e41210000000000006044820152606401610a9f565b81516004908181111561327c5761327c6158e0565b106132c95760405162461bcd60e51b815260206004820152601860248201527f446976696e65732063616e6e6f742062652066757365642100000000000000006044820152606401610a9f565b816020015160048111156132df576132df6158e0565b336000908152601560205260409020541161333c5760405162461bcd60e51b815260206004820152601760248201527f4861746368657279206c6576656c20746f6f206c6f77210000000000000000006044820152606401610a9f565b6133493361dead88610c99565b6133563361dead87610c99565b600061336133614052565b90506133ac6040805160e08101909152806000815260200160008152602001600061ffff168152602001600061ffff1681526020016000815260200160008152602001600081525090565b8351819060048111156133c1576133c16158e0565b908160048111156133d4576133d46158e0565b905250602084015160048111156133ed576133ed6158e0565b6133f8906001615bb3565b6004811115613409576134096158e0565b8160200190600481111561341f5761341f6158e0565b90816004811115613432576134326158e0565b8152505060028360400151856040015161344c9190615e7e565b6134569190615e99565b61ffff166040820181905261346c906032615e7e565b61ffff1660608201526080808401519085015160029161348b91615bb3565b6134959190615e6a565b60808201524260a082015260c080850151908201526000828152600f602052604090208151815483929190829060ff191660018360048111156134da576134da6158e0565b021790555060208201518154829061ff001916610100836004811115613502576135026158e0565b021790555060408201518154606084015161ffff9081166401000000000265ffff00000000199190931662010000021665ffffffff000019909116171781556080820151600182015560a0820151600282015560c09182015160039091015581015161356e90836140a8565b8187897fa98b671c87bd857dcf27da0b14ce098caa264ce385778aacc8f900b1502bb98960405160405180910390a45050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610981575061098182614578565b600061360882611816565b9050806001600160a01b0316836001600160a01b0316036136915760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610a9f565b336001600160a01b03821614806136ad57506136ad81336124c6565b61371f5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a9f565b610d20838361465b565b60008060005b84811015613973576012546001600160a01b0316638363871087878481811061375a5761375a615bf0565b905060200201356040518263ffffffff1660e01b815260040161377f91815260200190565b602060405180830381865afa15801561379c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c09190615e34565b6001600160a01b0316336001600160a01b0316148061387857506012546001600160a01b031663f658518a8787848181106137fd576137fd615bf0565b905060200201356040518263ffffffff1660e01b815260040161382291815260200190565b602060405180830381865afa15801561383f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138639190615e34565b6001600160a01b0316336001600160a01b0316145b6138c45760405162461bcd60e51b815260206004820152601960248201527f4e6f7420617070726f76656420746f207370656e6420474f4f000000000000006044820152606401610a9f565b6013546001600160a01b0316639cc7f7088787848181106138e7576138e7615bf0565b905060200201356040518263ffffffff1660e01b815260040161390c91815260200190565b602060405180830381865afa158015613929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061394d9190615e51565b6139579083615bb3565b915083821015613973578061396b81615c06565b91505061372f565b50828110156139c45760405162461bcd60e51b815260206004820152600f60248201527f4e6f7420656e6f75676820474f4f2100000000000000000000000000000000006044820152606401610a9f565b82915060005b84811015613dbc5760008686838181106139e6576139e6615bf0565b6013546040517f9cc7f70800000000000000000000000000000000000000000000000000000000815260209290920293909301356004820181905293506000926001600160a01b03169150639cc7f70890602401602060405180830381865afa158015613a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a7b9190615e51565b6012546040517f83638710000000000000000000000000000000000000000000000000000000008152600481018590529192506000916001600160a01b0390911690638363871090602401602060405180830381865afa158015613ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b079190615e34565b905086821015613c61576012546040516323b872dd60e01b81526001600160a01b03838116600483015230602483015260448201869052909116906323b872dd90606401600060405180830381600087803b158015613b6557600080fd5b505af1158015613b79573d6000803e3d6000fd5b505060135460405163b390c0ab60e01b815260048101879052602481018690526001600160a01b03909116925063b390c0ab9150604401600060405180830381600087803b158015613bca57600080fd5b505af1158015613bde573d6000803e3d6000fd5b50506012546040516323b872dd60e01b81523060048201526001600160a01b0385811660248301526044820188905290911692506323b872dd9150606401600060405180830381600087803b158015613c3657600080fd5b505af1158015613c4a573d6000803e3d6000fd5b505050508187613c5a9190615bdd565b9650613da6565b6012546040516323b872dd60e01b81526001600160a01b03838116600483015230602483015260448201869052909116906323b872dd90606401600060405180830381600087803b158015613cb557600080fd5b505af1158015613cc9573d6000803e3d6000fd5b505060135460405163b390c0ab60e01b815260048101879052602481018b90526001600160a01b03909116925063b390c0ab9150604401600060405180830381600087803b158015613d1a57600080fd5b505af1158015613d2e573d6000803e3d6000fd5b50506012546040516323b872dd60e01b81523060048201526001600160a01b0385811660248301526044820188905290911692506323b872dd9150606401600060405180830381600087803b158015613d8657600080fd5b505af1158015613d9a573d6000803e3d6000fd5b50505050505050613dbc565b5050508080613db490615c06565b9150506139ca565b50509392505050565b600061252a83836146d6565b826001600160a01b0316613de482611816565b6001600160a01b031614613e605760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610a9f565b6001600160a01b038216613edb5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a9f565b613ee68383836147be565b613ef160008261465b565b6001600160a01b0383166000908152600360205260408120805460019290613f1a908490615bdd565b90915550506001600160a01b0382166000908152600360205260408120805460019290613f48908490615bb3565b9091555050600081815260026020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600b5460ff166140085760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a9f565b600b805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60008061405d61480f565b9050614069838261481f565b61409a8161407683614839565b6040516020016140869190615eba565b60405160208183030381529060405261496e565b610981600c80546001019055565b600082815260116020908152604080832054601083528184208185529092529091208290556140d8816001615bb3565b600093845260116020526040909320929092555050565b6000806140fb84614a10565b9050600080846001161161411757670de0b6b3a7640000614119565b815b9050600184901c5b8015614151576141318384614a64565b92506001811615614149576141468284614a64565b91505b60011c614121565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156141ae576040517fffb15bcd00000000000000000000000000000000000000000000000000000000815260048101839052602401610a9f565b600080871280156141c25750856001166001145b9050806141cf57826141d8565b6141d883615efb565b979650505050505050565b6000600160ff1b8314806141fa5750600160ff1b82145b15614231576040517fb3c754a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600085126142425784614247565b846000035b915060008412614257578361425c565b836000035b9050600061427383670de0b6b3a764000084614b5d565b90507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156142d2576040517f7cb4bef500000000000000000000000000000000000000000000000000000000815260048101829052602401610a9f565b6000198087139086138082186001146142eb5782612324565b61232483615efb565b600b80546001600160a01b038381166101008181027fffffffffffffffffffffff0000000000000000000000000000000000000000ff85161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600b5460ff16156143ab5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b600b805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586140353390565b816001600160a01b0316836001600160a01b0316036144415760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a9f565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6144b9848484613dd1565b6144c584848484614c42565b611e215760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a9f565b6060600e805461099690615b69565b60006714057b7ef767814f670de0b6b3a764000061456384614de3565b028161457157614571615d2e565b0592915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061460b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061098157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610981565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416908117909155819061469d82611816565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166147605760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610a9f565b600061476b83611816565b9050806001600160a01b0316846001600160a01b031614806147a65750836001600160a01b031661479b84610a19565b6001600160a01b0316145b806147b657506147b681856124c6565b949350505050565b600b5460ff16156148045760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b610d20838383614ef8565b600061481a600c5490565b905090565b610ace828260405180602001604052806000815250614fb0565b60608160000361487c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156148a6578061489081615c06565b915061489f9050600a83615e6a565b9150614880565b60008167ffffffffffffffff8111156148c1576148c1615699565b6040519080825280601f01601f1916602001820160405280156148eb576020820181803683370190505b5090505b84156147b657614900600183615bdd565b915061490d600a86615f10565b614918906030615bb3565b60f81b81838151811061492d5761492d615bf0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350614967600a86615e6a565b94506148ef565b6000828152600260205260409020546001600160a01b03166149f85760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201527f6578697374656e7420746f6b656e0000000000000000000000000000000000006064820152608401610a9f565b6000828152600a60205260409020610d208282615c6e565b6000600160ff1b8203614a4f576040517f741d0b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008212614a5d5781610981565b5060000390565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110614ac1576040517fd31b340200000000000000000000000000000000000000000000000000000000815260048101829052602401610a9f565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff8211905082600003614aff5780670de0b6b3a7640000850401945050505050610981565b6204000082850304939091119091037d40000000000000000000000000000000000000000000000000000000000002919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b6000808060001985870985870292508281108382030391505080600003614b9757838281614b8d57614b8d615d2e565b049250505061252a565b838110614bda576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610a9f565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b60006001600160a01b0384163b15614dd8576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290614c9f903390899088908890600401615f24565b6020604051808303816000875af1925050508015614cda575060408051601f3d908101601f19168201909252614cd791810190615f60565b60015b614d8d573d808015614d08576040519150601f19603f3d011682016040523d82523d6000602084013e614d0d565b606091505b508051600003614d855760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a9f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001490506147b6565b506001949350505050565b6000808213614e21576040517f613f4fba00000000000000000000000000000000000000000000000000000000815260048101839052602401610a9f565b6000670de0b6b3a76400008312614e3a57506001614e54565b6000199050826ec097ce7bc90715b34b9f10000000000492505b6000614e69670de0b6b3a76400008505615039565b670de0b6b3a764000081029350905083811d7ffffffffffffffffffffffffffffffffffffffffffffffffff21f494c589c00008101614eaa57505002919050565b6706f05b59d3b200005b6000811315614eef57670de0b6b3a7640000828002059150671bc16d674ec800008212614ee7579384019360019190911d905b60011d614eb4565b50505002919050565b6001600160a01b038316614f5357614f4e81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b614f76565b816001600160a01b0316836001600160a01b031614614f7657614f76838261512a565b6001600160a01b038216614f8d57610d20816151c7565b826001600160a01b0316826001600160a01b031614610d2057610d208282615276565b614fba83836152ba565b614fc76000848484614c42565b610d205760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a9f565b6000700100000000000000000000000000000000821061506657608091821c916150639082615bb3565b90505b68010000000000000000821061508957604091821c916150869082615bb3565b90505b64010000000082106150a857602091821c916150a59082615bb3565b90505b6201000082106150c557601091821c916150c29082615bb3565b90505b61010082106150e157600891821c916150de9082615bb3565b90505b601082106150fc57600491821c916150f99082615bb3565b90505b6004821061511757600291821c916151149082615bb3565b90505b60028210610c9457610981600182615bb3565b60006001615137846118e2565b6151419190615bdd565b600083815260076020526040902054909150808214615194576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906151d990600190615bdd565b6000838152600960205260408120546008805493945090928490811061520157615201615bf0565b90600052602060002001549050806008838154811061522257615222615bf0565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061525a5761525a615f7d565b6001900381819060005260206000200160009055905550505050565b6000615281836118e2565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b0382166153105760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a9f565b6000818152600260205260409020546001600160a01b0316156153755760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a9f565b615381600083836147be565b6001600160a01b03821660009081526003602052604081208054600192906153aa908490615bb3565b9091555050600081815260026020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612efd57600080fd5b60006020828403121561545557600080fd5b813561252a81615415565b60005b8381101561547b578181015183820152602001615463565b50506000910152565b6000815180845261549c816020860160208601615460565b601f01601f19169290920160200192915050565b60208152600061252a6020830184615484565b6000602082840312156154d557600080fd5b5035919050565b6001600160a01b0381168114612efd57600080fd5b6000806040838503121561550457600080fd5b823561550f816154dc565b946020939093013593505050565b60008083601f84011261552f57600080fd5b50813567ffffffffffffffff81111561554757600080fd5b6020830191508360208260051b850101111561556257600080fd5b9250929050565b6000806020838503121561557c57600080fd5b823567ffffffffffffffff81111561559357600080fd5b61559f8582860161551d565b90969095509350505050565b6000806000606084860312156155c057600080fd5b83356155cb816154dc565b925060208401356155db816154dc565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b8181101561562457835183529284019291840191600101615608565b50909695505050505050565b803560058110610c9457600080fd5b60006020828403121561565157600080fd5b61252a82615630565b60006020828403121561566c57600080fd5b813561252a816154dc565b6000806040838503121561568a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156156ca576156ca615699565b604051601f8501601f19908116603f011681019082821181831017156156f2576156f2615699565b8160405280935085815286868601111561570b57600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561573757600080fd5b813567ffffffffffffffff81111561574e57600080fd5b8201601f8101841361575f57600080fd5b6147b6848235602084016156af565b60008060006040848603121561578357600080fd5b833567ffffffffffffffff81111561579a57600080fd5b6157a68682870161551d565b909790965060209590950135949350505050565b600080604083850312156157cd57600080fd5b61550f83615630565b600080600080600080606087890312156157ef57600080fd5b863567ffffffffffffffff8082111561580757600080fd5b6158138a838b0161551d565b9098509650602089013591508082111561582c57600080fd5b6158388a838b0161551d565b9096509450604089013591508082111561585157600080fd5b5061585e89828a0161551d565b979a9699509497509295939492505050565b6000806040838503121561588357600080fd5b823561588e816154dc565b9150602083013580151581146158a357600080fd5b809150509250929050565b600080600080608085870312156158c457600080fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b600052602160045260246000fd5b60058110612efd57634e487b7160e01b600052602160045260246000fd5b60608101615921856158f6565b93815260208101929092526001600160a01b031660409091015290565b6000806000806080858703121561595457600080fd5b843561595f816154dc565b9350602085013561596f816154dc565b925060408501359150606085013567ffffffffffffffff81111561599257600080fd5b8501601f810187136159a357600080fd5b6159b2878235602084016156af565b91505092959194509250565b803561ffff81168114610c9457600080fd5b600080600080608085870312156159e657600080fd5b6159ef856159be565b93506159fd602086016159be565b9250615a0b604086016159be565b9150615a19606086016159be565b905092959194509250565b60008060408385031215615a3757600080fd5b8235615a42816154dc565b915060208301356158a3816154dc565b60008060008060608587031215615a6857600080fd5b843567ffffffffffffffff811115615a7f57600080fd5b615a8b8782880161551d565b90989097506020870135966040013595509350505050565b600080600060608486031215615ab857600080fd5b83359250615ac860208501615630565b91506040840135615ad8816154dc565b809150509250925092565b600080600080600060a08688031215615afb57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60e08101615b2b896158f6565b888252615b37886158f6565b602082019790975261ffff9586166040820152939094166060840152608083019190915260a082015260c00152919050565b600181811c90821680615b7d57607f821691505b602082108103610de957634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561098157610981615b9d565b808202811582820484141761098157610981615b9d565b8181038181111561098157610981615b9d565b634e487b7160e01b600052603260045260246000fd5b60006000198203615c1957615c19615b9d565b5060010190565b601f821115610d2057600081815260208120601f850160051c81016020861015615c475750805b601f850160051c820191505b81811015615c6657828155600101615c53565b505050505050565b815167ffffffffffffffff811115615c8857615c88615699565b615c9c81615c968454615b69565b84615c20565b602080601f831160018114615cd15760008415615cb95750858301515b600019600386901b1c1916600185901b178555615c66565b600085815260208120601f198616915b82811015615d0057888601518255948401946001909101908401615ce1565b5085821015615d1e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601260045260246000fd5b600082615d5357615d53615d2e565b6000198314600160ff1b83141615615d6d57615d6d615b9d565b500590565b8181036000831280158383131683831282161715615d9257615d92615b9d565b5092915050565b80820260008212600160ff1b84141615615db557615db5615b9d565b818105831482151761098157610981615b9d565b60008451615ddb818460208901615460565b845190830190615def818360208901615460565b8451910190615e02818360208801615460565b7f77626567672e6a736f6e000000000000000000000000000000000000000000009101908152600a0195945050505050565b600060208284031215615e4657600080fd5b815161252a816154dc565b600060208284031215615e6357600080fd5b5051919050565b600082615e7957615e79615d2e565b500490565b61ffff818116838216019080821115615d9257615d92615b9d565b600061ffff80841680615eae57615eae615d2e565b92169190910492915050565b60008251615ecc818460208701615460565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000920191825250600501919050565b6000600160ff1b8203614a5d57614a5d615b9d565b600082615f1f57615f1f615d2e565b500690565b60006001600160a01b03808716835280861660208401525083604083015260806060830152615f566080830184615484565b9695505050505050565b600060208284031215615f7257600080fd5b815161252a81615415565b634e487b7160e01b600052603160045260246000fdfea264697066735822122042c1130d2195b44758719da073a973a8bb630f97dfe30aeaf62045a8edb5d4c464736f6c6343000811003300000000000000000000000058a15701ed1ad95bba625a05f41e50dce62aa14e00000000000000000000000082ced323fae774d7aedf822724be5cd1c58548c4
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104205760003560e01c8063666fa18611610235578063b423156311610135578063e994193b116100c8578063ed3cad1f11610097578063f2fde38b1161007c578063f2fde38b146108e5578063f68858e4146108f8578063feb40f7e1461090b57600080fd5b8063ed3cad1f146108bc578063f17aaf0c146108d257600080fd5b8063e994193b1461087a578063eaafba131461088d578063eb27def6146108a0578063ec0e262b146108b357600080fd5b8063c87b56dd11610104578063c87b56dd14610839578063cd58863f1461084c578063dbddb26a1461085f578063e985e9c51461086757600080fd5b8063b4231563146107b4578063b88d4fde146107ff578063c00bb57814610812578063c3bc86b91461082557600080fd5b80638da5cb5b116101c85780639a1b288511610197578063a22cb4651161017c578063a22cb4651461077b578063a4d225351461078e578063b25ec0b8146107a157600080fd5b80639a1b288514610769578063a1c1c1921461077257600080fd5b80638da5cb5b1461072f578063937113ac1461074557806394f568dd1461074e57806395d89b411461076157600080fd5b806378a3b9801161020457806378a3b980146106ee5780638147e01e146107015780638456cb59146107145780638784fde81461071c57600080fd5b8063666fa186146106b25780636d25571a146106ca57806370a08231146106d3578063715018a6146106e657600080fd5b80633c7d702211610340578063560de6fe116102d357806362617b92116102a25780636389263a116102875780636389263a1461068d57806364c4b56d146106a05780636503b88e146106a957600080fd5b806362617b92146106675780636352211e1461067a57600080fd5b8063560de6fe1461062057806359c6f87a146106295780635bbaee671461063c5780635c975abb1461065c57600080fd5b80634d90769b1161030f5780634d90769b146105d45780634f6ccce7146105e757806354e957b4146105fa57806355f804b31461060d57600080fd5b80633c7d7022146105905780633f4ba83a1461059957806342842e0e146105a15780634540b8ae146105b457600080fd5b806318160ddd116103b85780632f745c59116103875780632f745c591461054e57806333573dc214610561578063375f2b961461056a57806338da342a1461057d57600080fd5b806318160ddd1461050057806323b872dd146105085780632688a3341461051b578063274cdd5c1461053b57600080fd5b8063095ea7b3116103f4578063095ea7b3146104ae5780630f800356146104c357806312f4b154146104d6578063151c8fc5146104ed57600080fd5b806282f1aa1461042557806301ffc9a71461044b57806306fdde031461046e578063081812fc14610483575b600080fd5b601b546104339061ffff1681565b60405161ffff90911681526020015b60405180910390f35b61045e610459366004615443565b610976565b6040519015158152602001610442565b610476610987565b60405161044291906154b0565b6104966104913660046154c3565b610a19565b6040516001600160a01b039091168152602001610442565b6104c16104bc3660046154f1565b610ac4565b005b6104c16104d1366004615569565b610ad2565b6104df60175481565b604051908152602001610442565b6104df6104fb3660046154c3565b610bf4565b6008546104df565b6104c16105163660046155ab565b610c99565b61052e6105293660046154c3565b610d25565b60405161044291906155ec565b601354610496906001600160a01b031681565b6104df61055c3660046154f1565b610def565b6104df60185481565b6104df61057836600461563f565b610e97565b6104c161058b3660046154c3565b610f51565b6104df60205481565b6104c1610fb6565b6104c16105af3660046155ab565b611020565b6104df6105c23660046154c3565b60009081526011602052604090205490565b6104c16105e236600461565a565b61103b565b6104df6105f53660046154c3565b6110ca565b6104df610608366004615677565b61116e565b6104c161061b366004615725565b6111e9565b6104df601d5481565b6104c161063736600461576e565b611255565b6104df61064a36600461565a565b60156020526000908152604090205481565b600b5460ff1661045e565b6104df6106753660046157ba565b611787565b6104966106883660046154c3565b611816565b6104df61069b3660046157ba565b6118a1565b6104df601f5481565b6104df601a5481565b601b54610433906601000000000000900461ffff1681565b6104df601c5481565b6104df6106e136600461565a565b6118e2565b6104c161197c565b6104c16106fc36600461565a565b6119e6565b601254610496906001600160a01b031681565b6104c1611a75565b6104c161072a3660046157d6565b611add565b600b5461010090046001600160a01b0316610496565b6104df60165481565b6104df61075c3660046154c3565b611bcd565b610476611c9c565b6104df60195481565b6104df601e5481565b6104c1610789366004615870565b611cab565b61049661079c3660046154c3565b611cb6565b6104c16107af3660046158ae565b611d25565b6107f06107c23660046154c3565b60146020526000908152604090208054600182015460029092015460ff90911691906001600160a01b031683565b60405161044293929190615914565b6104c161080d36600461593e565b611d99565b61043361082036600461563f565b611e27565b601b546104339062010000900461ffff1681565b6104766108473660046154c3565b611ed7565b6104c161085a3660046159d0565b612330565b610476612438565b61045e610875366004615a24565b6124c6565b6104c1610888366004615a52565b612531565b6104c161089b366004615aa3565b612b12565b6104336108ae366004615677565b612c42565b6104df60215481565b601b5461043390640100000000900461ffff1681565b6104c16108e0366004615ae3565b612da1565b6104c16108f336600461565a565b612e18565b6104c1610906366004615677565b612f00565b6109636109193660046154c3565b6000908152600f6020526040902080546001820154600283015460039093015460ff8084169561010085049091169461ffff62010000860481169564010000000090041693929091565b6040516104429796959493929190615b1e565b6000610981826135a7565b92915050565b60606000805461099690615b69565b80601f01602080910402602001604051908101604052809291908181526020018280546109c290615b69565b8015610a0f5780601f106109e457610100808354040283529160200191610a0f565b820191906000526020600020905b8154815290600101906020018083116109f257829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610aa85760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b610ace82826135fd565b5050565b600b5460ff1615610b185760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b33600090815260156020526040902054601c548110610b795760405162461bcd60e51b815260206004820152601560248201527f4861746368657279206973206d6178206c6576656c00000000000000000000006044820152606401610a9f565b6000610b8482610bf4565b9050610b91848483613729565b50336000908152601560205260408120805460019290610bb2908490615bb3565b90915550610bc39050826001615bb3565b60405133907f318d2be9b9a887c0d168715bd2f44017dafbb3360b14cdcc2a8c0086b4e2d15190600090a350505050565b600081600003610c1357601d5461098190670de0b6b3a7640000615bc6565b81600103610c3057601e5461098190670de0b6b3a7640000615bc6565b81600203610c4d57601f5461098190670de0b6b3a7640000615bc6565b81600303610c6a5760205461098190670de0b6b3a7640000615bc6565b610c75600383615bdd565b602154610c829190615bc6565b61098190670de0b6b3a7640000615bc6565b919050565b610ca33382613dc5565b610d155760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a9f565b610d20838383613dd1565b505050565b600081815260116020526040812054606091819003610d585760408051600080825260208201909252905b509392505050565b60008167ffffffffffffffff811115610d7357610d73615699565b604051908082528060200260200182016040528015610d9c578160200160208202803683370190505b50905060005b82811015610d50576000610db6868361116e565b905080838381518110610dcb57610dcb615bf0565b60209081029190910101525080610de181615c06565b915050610da2565b50919050565b6000610dfa836118e2565b8210610e6e5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610a9f565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000816004811115610eab57610eab6158e0565b600003610ec75760175461098190670de0b6b3a7640000615bc6565b816004811115610ed957610ed96158e0565b600103610ef55760185461098190670de0b6b3a7640000615bc6565b816004811115610f0757610f076158e0565b600203610f235760195461098190670de0b6b3a7640000615bc6565b6003826004811115610f3757610f376158e0565b10610c9457601a5461098190670de0b6b3a7640000615bc6565b600b546001600160a01b03610100909104163314610fb15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601c55565b600b546001600160a01b036101009091041633146110165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b61101e613fb6565b565b610d2083838360405180602001604052806000815250611d99565b600b546001600160a01b0361010090910416331461109b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b6013805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60006110d560085490565b82106111495760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610a9f565b6008828154811061115c5761115c615bf0565b90600052602060002001549050919050565b60008281526011602052604081205482106111cb5760405162461bcd60e51b815260206004820152601d60248201527f456767206f776e657220696e646578206f7574206f6620626f756e64730000006044820152606401610a9f565b50600091825260106020908152604080842092845291905290205490565b600b546001600160a01b036101009091041633146112495760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b600e610ace8282615c6e565b600b5460ff161561129b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b60008181526014602052604080822081516060810190925280548493929190829060ff1660048111156112d0576112d06158e0565b60048111156112e1576112e16158e0565b8152600182015460208201526002909101546001600160a01b03908116604092830152908201519192501633146113495760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b82600061135582610d25565b905060005b815181101561154c576000600f600084848151811061137b5761137b615bf0565b602002602001015181526020019081526020016000206040518060e00160405290816000820160009054906101000a900460ff1660048111156113c0576113c06158e0565b60048111156113d1576113d16158e0565b81528154602090910190610100900460ff1660048111156113f4576113f46158e0565b6004811115611405576114056158e0565b8152815461ffff62010000820481166020840152640100000000909104166040820152600182015460608201526002820154608082015260039091015460a0909101529050600081602001516004811115611462576114626158e0565b1480156114725750838160c00151145b156115395760165442118015611498575062015180601654426114959190615bdd565b10155b806114c757508060a001516016541180156114c75750620151808160a001516016546114c49190615bdd565b10155b6115395760405162461bcd60e51b815260206004820152602c60248201527f42656172206e656564732074696d65206265666f726520737061776e696e672060448201527f616e6f74686572206567672100000000000000000000000000000000000000006064820152608401610a9f565b508061154481615c06565b91505061135a565b505b6016544211801561156e5750620151806016544261156c9190615bdd565b115b156115935762015180601660008282546115889190615bb3565b9091555061154e9050565b600085815260146020526040812080549091906115b29060ff16610e97565b905060006115c18a8a84613729565b9050808360010160008282546115d79190615bb3565b90915550600090506115e833614052565b90506116336040805160e08101909152806000815260200160008152602001600061ffff168152602001600061ffff1681526020016000815260200160008152602001600081525090565b600060208201528454819060ff166004811115611652576116526158e0565b90816004811115611665576116656158e0565b9052504260a082015260c081018a9052805161168090611e27565b61ffff1660608201526000828152600f602052604090208151815483929190829060ff191660018360048111156116b9576116b96158e0565b021790555060208201518154829061ff0019166101008360048111156116e1576116e16158e0565b021790555060408201518154606084015161ffff9081166401000000000265ffff00000000199190931662010000021665ffffffff000019909116171781556080820151600182015560a0820151600282015560c09091015160039091015561174a8a836140a8565b828a837fd08d1e82229a1d0f8cd0a1da06c35f597af0438b2690e2288fe64999b6df50a660405160405180910390a4505050505050505050505050565b6000806064670de0b6b3a764000061179e86610e97565b6117a89190615d44565b6117b29190615d44565b905060006118036117cb670e92596fd6290000866140ef565b6117dd90670de0b6b3a7640000615d72565b7fffffffffffffffffffffffffffffffffffffffffffffffffff4e5d43d13b00006141e3565b61180d9083615d99565b95945050505050565b6000818152600260205260408120546001600160a01b0316806109815760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610a9f565b6000806064670de0b6b3a76400006118b886610e97565b6118c29190615d44565b6118cc9190615d44565b90506000611803670e92596fd6290000856140ef565b60006001600160a01b0382166119605760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610a9f565b506001600160a01b031660009081526003602052604090205490565b600b546001600160a01b036101009091041633146119dc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b61101e60006142f4565b600b546001600160a01b03610100909104163314611a465760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b6012805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600b546001600160a01b03610100909104163314611ad55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b61101e614365565b600b546001600160a01b03610100909104163314611b3d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b60005b85811015611bc457611bb2878783818110611b5d57611b5d615bf0565b90506020020135868684818110611b7657611b76615bf0565b9050602002016020810190611b8b919061563f565b858585818110611b9d57611b9d615bf0565b905060200201602081019061089b919061565a565b80611bbc81615c06565b915050611b40565b50505050505050565b6000818152600f6020526040808220815160e08101909252805483929190829060ff166004811115611c0157611c016158e0565b6004811115611c1257611c126158e0565b81528154602090910190610100900460ff166004811115611c3557611c356158e0565b6004811115611c4657611c466158e0565b8152815461ffff620100008204811660208401526401000000009091048116604083015260018301546060808401919091526002840154608084015260039093015460a090920191909152910151169392505050565b60606001805461099690615b69565b610ace3383836143e0565b600081815260146020526040808220815160608101909252805483929190829060ff166004811115611cea57611cea6158e0565b6004811115611cfb57611cfb6158e0565b8152600182015460208201526002909101546001600160a01b031660409182015201519392505050565b600b546001600160a01b03610100909104163314611d855760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601793909355601891909155601955601a55565b611da33383613dc5565b611e155760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a9f565b611e21848484846144ae565b50505050565b6000816004811115611e3b57611e3b6158e0565b600003611e4e575050601b5461ffff1690565b816004811115611e6057611e606158e0565b600103611e7a5750601b5462010000900461ffff16919050565b816004811115611e8c57611e8c6158e0565b600203611ea85750601b54640100000000900461ffff16919050565b6003826004811115611ebc57611ebc6158e0565b10610c94575050601b546601000000000000900461ffff1690565b6000818152600260205260409020546060906001600160a01b0316611f645760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610a9f565b6000611f6e614537565b6000848152600f6020526040808220815160e0810190925280549394509192909190829060ff166004811115611fa657611fa66158e0565b6004811115611fb757611fb76158e0565b81528154602090910190610100900460ff166004811115611fda57611fda6158e0565b6004811115611feb57611feb6158e0565b8152815461ffff62010000820481166020840152640100000000909104166040820152600182015460608201526002820154608082015260039091015460a09091015280519091506000906004811115612047576120476158e0565b9050600082602001516004811115612061576120616158e0565b604080518082018252600881527f7374616e646172640000000000000000000000000000000000000000000000006020808301919091528251808401909352600683527f636f6d6d6f6e0000000000000000000000000000000000000000000000000000908301529192506001849003612112576040518060400160405280600481526020017f736572660000000000000000000000000000000000000000000000000000000081525091506121dd565b83600203612157576040518060400160405280600981526020017f696e76697369626c65000000000000000000000000000000000000000000000081525091506121dd565b8360030361219c576040518060400160405280600381526020017f696365000000000000000000000000000000000000000000000000000000000081525091506121dd565b836004036121dd576040518060400160405280600481526020017f6461726b0000000000000000000000000000000000000000000000000000000081525091505b8260010361221f575060408051808201909152600481527f726172650000000000000000000000000000000000000000000000000000000060208201526122e1565b82600203612261575060408051808201909152600981527f6c6567656e64617279000000000000000000000000000000000000000000000060208201526122e1565b826003036122a3575060408051808201909152600781527f6578616c7465640000000000000000000000000000000000000000000000000060208201526122e1565b826004036122e1575060408051808201909152600681527f646976696e65000000000000000000000000000000000000000000000000000060208201525b60008651116122ff5760405180602001604052806000815250612324565b85828260405160200161231493929190615dc9565b6040516020818303038152906040525b98975050505050505050565b600b546001600160a01b036101009091041633146123905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601b805461ffff9586167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000909116176201000094861694909402939093177fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff16640100000000928516929092027fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff169190911766010000000000009190931602919091179055565b600e805461244590615b69565b80601f016020809104026020016040519081016040528092919081815260200182805461247190615b69565b80156124be5780601f10612493576101008083540402835291602001916124be565b820191906000526020600020905b8154815290600101906020018083116124a157829003601f168201915b505050505081565b60007fffffffffffffffffffffffffa77f8452f4c89103ed0a52795538f187129821526001600160a01b0383160161250057506001610981565b6001600160a01b0380841660009081526005602090815260408083209386168352929052205460ff165b9392505050565b600b5460ff16156125775760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b8161258181611816565b6001600160a01b0316336001600160a01b0316146125d05760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b6000838152600f60205260408120906125f184670de0b6b3a7640000615bc6565b905060006125fe86611bcd565b600184015484549192506000916126189060ff1684611787565b6126229190615bdd565b845490915062010000900461ffff168211801561263f5750600081115b61268b5760405162461bcd60e51b815260206004820152601d60248201527f456767206174206d6178206c6576656c212054727920667573696e672e0000006044820152606401610a9f565b6000805b89811015612a7d5760008b8b838181106126ab576126ab615bf0565b6012546040517f8363871000000000000000000000000000000000000000000000000000000000815260209290920293909301356004820181905293506000926001600160a01b03169150638363871090602401602060405180830381865afa15801561271c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127409190615e34565b9050336001600160a01b03821614806127ef57506012546040517ff658518a000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b039091169063f658518a90602401602060405180830381865afa1580156127b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127da9190615e34565b6001600160a01b0316336001600160a01b0316145b61283b5760405162461bcd60e51b815260206004820152601960248201527f4e6f7420617070726f76656420746f207370656e6420474f4f000000000000006044820152606401610a9f565b6013546040517f9cc7f708000000000000000000000000000000000000000000000000000000008152600481018490526000916001600160a01b031690639cc7f70890602401602060405180830381865afa15801561289e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c29190615e51565b9050876128cf8287615bb3565b11156128e2576128df8589615bdd565b90505b856128ed8287615bb3565b1115612900576128fd8587615bdd565b90505b6012546040516323b872dd60e01b81526001600160a01b03848116600483015230602483015260448201869052909116906323b872dd90606401600060405180830381600087803b15801561295457600080fd5b505af1158015612968573d6000803e3d6000fd5b505060135460405163b390c0ab60e01b815260048101879052602481018590526001600160a01b03909116925063b390c0ab9150604401600060405180830381600087803b1580156129b957600080fd5b505af11580156129cd573d6000803e3d6000fd5b50506012546040516323b872dd60e01b81523060048201526001600160a01b0386811660248301526044820188905290911692506323b872dd9150606401600060405180830381600087803b158015612a2557600080fd5b505af1158015612a39573d6000803e3d6000fd5b505050508085612a499190615bb3565b94508585101580612a5a5750878510155b15612a6757505050612a7d565b5050508080612a7590615c06565b91505061268f565b50612a888882612c42565b855461ffff9190911662010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff909116178555600185018054829190600090612ad4908490615bb3565b9091555050604051819089907f9bf12cd03cc3b97f3d2a6b9fc65dd54bd989e3b1e70b761b03dffb6054d26a3090600090a350505050505050505050565b600b546001600160a01b03610100909104163314612b725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b604080516060810182526000808252602082018190529181019190915280836004811115612ba257612ba26158e0565b90816004811115612bb557612bb56158e0565b9052506001600160a01b03821660408083019190915260008581526014602052208151815483929190829060ff19166001836004811115612bf857612bf86158e0565b0217905550602082015160018201556040909101516002909101805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0390921691909117905550505050565b6000828152600f6020526040808220815160e08101909252805483929190829060ff166004811115612c7657612c766158e0565b6004811115612c8757612c876158e0565b81528154602090910190610100900460ff166004811115612caa57612caa6158e0565b6004811115612cbb57612cbb6158e0565b8152815461ffff62010000820481166020840152640100000000909104166040820152600182015460608201526002820154608082015260039091015460a09091015290506000839003612d1457604001519050610981565b60006064612d258360000151610e97565b612d30906014615bc6565b612d3a9190615e6a565b9050600081858460800151612d4f9190615bb3565b612d599190615bb3565b90506000612d6782846141e3565b90506000612d8d612d7783614546565b612d88670e92596fd6290000614546565b6141e3565b9050612324670de0b6b3a764000082615d44565b600b546001600160a01b03610100909104163314612e015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b601d94909455601e92909255601f55602055602155565b600b546001600160a01b03610100909104163314612e785760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9f565b6001600160a01b038116612ef45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a9f565b612efd816142f4565b50565b600b5460ff1615612f465760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b81612f5081611816565b6001600160a01b0316336001600160a01b031614612f9f5760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b81612fa981611816565b6001600160a01b0316336001600160a01b031614612ff85760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610a9f565b6000848152600f6020526040808220815160e081019092528054829060ff166004811115613028576130286158e0565b6004811115613039576130396158e0565b81528154602090910190610100900460ff16600481111561305c5761305c6158e0565b600481111561306d5761306d6158e0565b8152815461ffff620100008204811660208085019190915264010000000090920416604080840191909152600184015460608401526002840154608084015260039093015460a0909201919091526000878152600f909152818120825160e0810190935280549394509092829060ff1660048111156130ee576130ee6158e0565b60048111156130ff576130ff6158e0565b81528154602090910190610100900460ff166004811115613122576131226158e0565b6004811115613133576131336158e0565b8152815461ffff6201000082048116602080850191909152640100000000909204166040830152600183015460608301526002830154608083015260039092015460a0909101528101519091506004811115613191576131916158e0565b826020015160048111156131a7576131a76158e0565b146131f45760405162461bcd60e51b815260206004820152601d60248201527f45676773206d757374206265207468652073616d6520726172697479210000006044820152606401610a9f565b80516004811115613207576132076158e0565b8251600481111561321a5761321a6158e0565b146132675760405162461bcd60e51b815260206004820152601a60248201527f45676773206d757374206265207468652073616d6520444e41210000000000006044820152606401610a9f565b81516004908181111561327c5761327c6158e0565b106132c95760405162461bcd60e51b815260206004820152601860248201527f446976696e65732063616e6e6f742062652066757365642100000000000000006044820152606401610a9f565b816020015160048111156132df576132df6158e0565b336000908152601560205260409020541161333c5760405162461bcd60e51b815260206004820152601760248201527f4861746368657279206c6576656c20746f6f206c6f77210000000000000000006044820152606401610a9f565b6133493361dead88610c99565b6133563361dead87610c99565b600061336133614052565b90506133ac6040805160e08101909152806000815260200160008152602001600061ffff168152602001600061ffff1681526020016000815260200160008152602001600081525090565b8351819060048111156133c1576133c16158e0565b908160048111156133d4576133d46158e0565b905250602084015160048111156133ed576133ed6158e0565b6133f8906001615bb3565b6004811115613409576134096158e0565b8160200190600481111561341f5761341f6158e0565b90816004811115613432576134326158e0565b8152505060028360400151856040015161344c9190615e7e565b6134569190615e99565b61ffff166040820181905261346c906032615e7e565b61ffff1660608201526080808401519085015160029161348b91615bb3565b6134959190615e6a565b60808201524260a082015260c080850151908201526000828152600f602052604090208151815483929190829060ff191660018360048111156134da576134da6158e0565b021790555060208201518154829061ff001916610100836004811115613502576135026158e0565b021790555060408201518154606084015161ffff9081166401000000000265ffff00000000199190931662010000021665ffffffff000019909116171781556080820151600182015560a0820151600282015560c09182015160039091015581015161356e90836140a8565b8187897fa98b671c87bd857dcf27da0b14ce098caa264ce385778aacc8f900b1502bb98960405160405180910390a45050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610981575061098182614578565b600061360882611816565b9050806001600160a01b0316836001600160a01b0316036136915760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610a9f565b336001600160a01b03821614806136ad57506136ad81336124c6565b61371f5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a9f565b610d20838361465b565b60008060005b84811015613973576012546001600160a01b0316638363871087878481811061375a5761375a615bf0565b905060200201356040518263ffffffff1660e01b815260040161377f91815260200190565b602060405180830381865afa15801561379c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137c09190615e34565b6001600160a01b0316336001600160a01b0316148061387857506012546001600160a01b031663f658518a8787848181106137fd576137fd615bf0565b905060200201356040518263ffffffff1660e01b815260040161382291815260200190565b602060405180830381865afa15801561383f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138639190615e34565b6001600160a01b0316336001600160a01b0316145b6138c45760405162461bcd60e51b815260206004820152601960248201527f4e6f7420617070726f76656420746f207370656e6420474f4f000000000000006044820152606401610a9f565b6013546001600160a01b0316639cc7f7088787848181106138e7576138e7615bf0565b905060200201356040518263ffffffff1660e01b815260040161390c91815260200190565b602060405180830381865afa158015613929573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061394d9190615e51565b6139579083615bb3565b915083821015613973578061396b81615c06565b91505061372f565b50828110156139c45760405162461bcd60e51b815260206004820152600f60248201527f4e6f7420656e6f75676820474f4f2100000000000000000000000000000000006044820152606401610a9f565b82915060005b84811015613dbc5760008686838181106139e6576139e6615bf0565b6013546040517f9cc7f70800000000000000000000000000000000000000000000000000000000815260209290920293909301356004820181905293506000926001600160a01b03169150639cc7f70890602401602060405180830381865afa158015613a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a7b9190615e51565b6012546040517f83638710000000000000000000000000000000000000000000000000000000008152600481018590529192506000916001600160a01b0390911690638363871090602401602060405180830381865afa158015613ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b079190615e34565b905086821015613c61576012546040516323b872dd60e01b81526001600160a01b03838116600483015230602483015260448201869052909116906323b872dd90606401600060405180830381600087803b158015613b6557600080fd5b505af1158015613b79573d6000803e3d6000fd5b505060135460405163b390c0ab60e01b815260048101879052602481018690526001600160a01b03909116925063b390c0ab9150604401600060405180830381600087803b158015613bca57600080fd5b505af1158015613bde573d6000803e3d6000fd5b50506012546040516323b872dd60e01b81523060048201526001600160a01b0385811660248301526044820188905290911692506323b872dd9150606401600060405180830381600087803b158015613c3657600080fd5b505af1158015613c4a573d6000803e3d6000fd5b505050508187613c5a9190615bdd565b9650613da6565b6012546040516323b872dd60e01b81526001600160a01b03838116600483015230602483015260448201869052909116906323b872dd90606401600060405180830381600087803b158015613cb557600080fd5b505af1158015613cc9573d6000803e3d6000fd5b505060135460405163b390c0ab60e01b815260048101879052602481018b90526001600160a01b03909116925063b390c0ab9150604401600060405180830381600087803b158015613d1a57600080fd5b505af1158015613d2e573d6000803e3d6000fd5b50506012546040516323b872dd60e01b81523060048201526001600160a01b0385811660248301526044820188905290911692506323b872dd9150606401600060405180830381600087803b158015613d8657600080fd5b505af1158015613d9a573d6000803e3d6000fd5b50505050505050613dbc565b5050508080613db490615c06565b9150506139ca565b50509392505050565b600061252a83836146d6565b826001600160a01b0316613de482611816565b6001600160a01b031614613e605760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e65720000000000000000000000000000000000000000000000000000006064820152608401610a9f565b6001600160a01b038216613edb5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a9f565b613ee68383836147be565b613ef160008261465b565b6001600160a01b0383166000908152600360205260408120805460019290613f1a908490615bdd565b90915550506001600160a01b0382166000908152600360205260408120805460019290613f48908490615bb3565b9091555050600081815260026020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600b5460ff166140085760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610a9f565b600b805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60008061405d61480f565b9050614069838261481f565b61409a8161407683614839565b6040516020016140869190615eba565b60405160208183030381529060405261496e565b610981600c80546001019055565b600082815260116020908152604080832054601083528184208185529092529091208290556140d8816001615bb3565b600093845260116020526040909320929092555050565b6000806140fb84614a10565b9050600080846001161161411757670de0b6b3a7640000614119565b815b9050600184901c5b8015614151576141318384614a64565b92506001811615614149576141468284614a64565b91505b60011c614121565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156141ae576040517fffb15bcd00000000000000000000000000000000000000000000000000000000815260048101839052602401610a9f565b600080871280156141c25750856001166001145b9050806141cf57826141d8565b6141d883615efb565b979650505050505050565b6000600160ff1b8314806141fa5750600160ff1b82145b15614231576040517fb3c754a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600085126142425784614247565b846000035b915060008412614257578361425c565b836000035b9050600061427383670de0b6b3a764000084614b5d565b90507f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156142d2576040517f7cb4bef500000000000000000000000000000000000000000000000000000000815260048101829052602401610a9f565b6000198087139086138082186001146142eb5782612324565b61232483615efb565b600b80546001600160a01b038381166101008181027fffffffffffffffffffffff0000000000000000000000000000000000000000ff85161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600b5460ff16156143ab5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b600b805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586140353390565b816001600160a01b0316836001600160a01b0316036144415760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a9f565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6144b9848484613dd1565b6144c584848484614c42565b611e215760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a9f565b6060600e805461099690615b69565b60006714057b7ef767814f670de0b6b3a764000061456384614de3565b028161457157614571615d2e565b0592915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061460b57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061098157507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610981565b6000818152600460205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038416908117909155819061469d82611816565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166147605760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610a9f565b600061476b83611816565b9050806001600160a01b0316846001600160a01b031614806147a65750836001600160a01b031661479b84610a19565b6001600160a01b0316145b806147b657506147b681856124c6565b949350505050565b600b5460ff16156148045760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610a9f565b610d20838383614ef8565b600061481a600c5490565b905090565b610ace828260405180602001604052806000815250614fb0565b60608160000361487c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156148a6578061489081615c06565b915061489f9050600a83615e6a565b9150614880565b60008167ffffffffffffffff8111156148c1576148c1615699565b6040519080825280601f01601f1916602001820160405280156148eb576020820181803683370190505b5090505b84156147b657614900600183615bdd565b915061490d600a86615f10565b614918906030615bb3565b60f81b81838151811061492d5761492d615bf0565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350614967600a86615e6a565b94506148ef565b6000828152600260205260409020546001600160a01b03166149f85760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201527f6578697374656e7420746f6b656e0000000000000000000000000000000000006064820152608401610a9f565b6000828152600a60205260409020610d208282615c6e565b6000600160ff1b8203614a4f576040517f741d0b8c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008212614a5d5781610981565b5060000390565b60008080600019848609848602925082811083820303915050670de0b6b3a76400008110614ac1576040517fd31b340200000000000000000000000000000000000000000000000000000000815260048101829052602401610a9f565b600080670de0b6b3a764000086880991506706f05b59d3b1ffff8211905082600003614aff5780670de0b6b3a7640000850401945050505050610981565b6204000082850304939091119091037d40000000000000000000000000000000000000000000000000000000000002919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b6000808060001985870985870292508281108382030391505080600003614b9757838281614b8d57614b8d615d2e565b049250505061252a565b838110614bda576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610a9f565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b60006001600160a01b0384163b15614dd8576040517f150b7a020000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063150b7a0290614c9f903390899088908890600401615f24565b6020604051808303816000875af1925050508015614cda575060408051601f3d908101601f19168201909252614cd791810190615f60565b60015b614d8d573d808015614d08576040519150601f19603f3d011682016040523d82523d6000602084013e614d0d565b606091505b508051600003614d855760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a9f565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001490506147b6565b506001949350505050565b6000808213614e21576040517f613f4fba00000000000000000000000000000000000000000000000000000000815260048101839052602401610a9f565b6000670de0b6b3a76400008312614e3a57506001614e54565b6000199050826ec097ce7bc90715b34b9f10000000000492505b6000614e69670de0b6b3a76400008505615039565b670de0b6b3a764000081029350905083811d7ffffffffffffffffffffffffffffffffffffffffffffffffff21f494c589c00008101614eaa57505002919050565b6706f05b59d3b200005b6000811315614eef57670de0b6b3a7640000828002059150671bc16d674ec800008212614ee7579384019360019190911d905b60011d614eb4565b50505002919050565b6001600160a01b038316614f5357614f4e81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b614f76565b816001600160a01b0316836001600160a01b031614614f7657614f76838261512a565b6001600160a01b038216614f8d57610d20816151c7565b826001600160a01b0316826001600160a01b031614610d2057610d208282615276565b614fba83836152ba565b614fc76000848484614c42565b610d205760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a9f565b6000700100000000000000000000000000000000821061506657608091821c916150639082615bb3565b90505b68010000000000000000821061508957604091821c916150869082615bb3565b90505b64010000000082106150a857602091821c916150a59082615bb3565b90505b6201000082106150c557601091821c916150c29082615bb3565b90505b61010082106150e157600891821c916150de9082615bb3565b90505b601082106150fc57600491821c916150f99082615bb3565b90505b6004821061511757600291821c916151149082615bb3565b90505b60028210610c9457610981600182615bb3565b60006001615137846118e2565b6151419190615bdd565b600083815260076020526040902054909150808214615194576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906151d990600190615bdd565b6000838152600960205260408120546008805493945090928490811061520157615201615bf0565b90600052602060002001549050806008838154811061522257615222615bf0565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061525a5761525a615f7d565b6001900381819060005260206000200160009055905550505050565b6000615281836118e2565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b0382166153105760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a9f565b6000818152600260205260409020546001600160a01b0316156153755760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a9f565b615381600083836147be565b6001600160a01b03821660009081526003602052604081208054600192906153aa908490615bb3565b9091555050600081815260026020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114612efd57600080fd5b60006020828403121561545557600080fd5b813561252a81615415565b60005b8381101561547b578181015183820152602001615463565b50506000910152565b6000815180845261549c816020860160208601615460565b601f01601f19169290920160200192915050565b60208152600061252a6020830184615484565b6000602082840312156154d557600080fd5b5035919050565b6001600160a01b0381168114612efd57600080fd5b6000806040838503121561550457600080fd5b823561550f816154dc565b946020939093013593505050565b60008083601f84011261552f57600080fd5b50813567ffffffffffffffff81111561554757600080fd5b6020830191508360208260051b850101111561556257600080fd5b9250929050565b6000806020838503121561557c57600080fd5b823567ffffffffffffffff81111561559357600080fd5b61559f8582860161551d565b90969095509350505050565b6000806000606084860312156155c057600080fd5b83356155cb816154dc565b925060208401356155db816154dc565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b8181101561562457835183529284019291840191600101615608565b50909695505050505050565b803560058110610c9457600080fd5b60006020828403121561565157600080fd5b61252a82615630565b60006020828403121561566c57600080fd5b813561252a816154dc565b6000806040838503121561568a57600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156156ca576156ca615699565b604051601f8501601f19908116603f011681019082821181831017156156f2576156f2615699565b8160405280935085815286868601111561570b57600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561573757600080fd5b813567ffffffffffffffff81111561574e57600080fd5b8201601f8101841361575f57600080fd5b6147b6848235602084016156af565b60008060006040848603121561578357600080fd5b833567ffffffffffffffff81111561579a57600080fd5b6157a68682870161551d565b909790965060209590950135949350505050565b600080604083850312156157cd57600080fd5b61550f83615630565b600080600080600080606087890312156157ef57600080fd5b863567ffffffffffffffff8082111561580757600080fd5b6158138a838b0161551d565b9098509650602089013591508082111561582c57600080fd5b6158388a838b0161551d565b9096509450604089013591508082111561585157600080fd5b5061585e89828a0161551d565b979a9699509497509295939492505050565b6000806040838503121561588357600080fd5b823561588e816154dc565b9150602083013580151581146158a357600080fd5b809150509250929050565b600080600080608085870312156158c457600080fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b600052602160045260246000fd5b60058110612efd57634e487b7160e01b600052602160045260246000fd5b60608101615921856158f6565b93815260208101929092526001600160a01b031660409091015290565b6000806000806080858703121561595457600080fd5b843561595f816154dc565b9350602085013561596f816154dc565b925060408501359150606085013567ffffffffffffffff81111561599257600080fd5b8501601f810187136159a357600080fd5b6159b2878235602084016156af565b91505092959194509250565b803561ffff81168114610c9457600080fd5b600080600080608085870312156159e657600080fd5b6159ef856159be565b93506159fd602086016159be565b9250615a0b604086016159be565b9150615a19606086016159be565b905092959194509250565b60008060408385031215615a3757600080fd5b8235615a42816154dc565b915060208301356158a3816154dc565b60008060008060608587031215615a6857600080fd5b843567ffffffffffffffff811115615a7f57600080fd5b615a8b8782880161551d565b90989097506020870135966040013595509350505050565b600080600060608486031215615ab857600080fd5b83359250615ac860208501615630565b91506040840135615ad8816154dc565b809150509250925092565b600080600080600060a08688031215615afb57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60e08101615b2b896158f6565b888252615b37886158f6565b602082019790975261ffff9586166040820152939094166060840152608083019190915260a082015260c00152919050565b600181811c90821680615b7d57607f821691505b602082108103610de957634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082018082111561098157610981615b9d565b808202811582820484141761098157610981615b9d565b8181038181111561098157610981615b9d565b634e487b7160e01b600052603260045260246000fd5b60006000198203615c1957615c19615b9d565b5060010190565b601f821115610d2057600081815260208120601f850160051c81016020861015615c475750805b601f850160051c820191505b81811015615c6657828155600101615c53565b505050505050565b815167ffffffffffffffff811115615c8857615c88615699565b615c9c81615c968454615b69565b84615c20565b602080601f831160018114615cd15760008415615cb95750858301515b600019600386901b1c1916600185901b178555615c66565b600085815260208120601f198616915b82811015615d0057888601518255948401946001909101908401615ce1565b5085821015615d1e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601260045260246000fd5b600082615d5357615d53615d2e565b6000198314600160ff1b83141615615d6d57615d6d615b9d565b500590565b8181036000831280158383131683831282161715615d9257615d92615b9d565b5092915050565b80820260008212600160ff1b84141615615db557615db5615b9d565b818105831482151761098157610981615b9d565b60008451615ddb818460208901615460565b845190830190615def818360208901615460565b8451910190615e02818360208801615460565b7f77626567672e6a736f6e000000000000000000000000000000000000000000009101908152600a0195945050505050565b600060208284031215615e4657600080fd5b815161252a816154dc565b600060208284031215615e6357600080fd5b5051919050565b600082615e7957615e79615d2e565b500490565b61ffff818116838216019080821115615d9257615d92615b9d565b600061ffff80841680615eae57615eae615d2e565b92169190910492915050565b60008251615ecc818460208701615460565b7f2e6a736f6e000000000000000000000000000000000000000000000000000000920191825250600501919050565b6000600160ff1b8203614a5d57614a5d615b9d565b600082615f1f57615f1f615d2e565b500690565b60006001600160a01b03808716835280861660208401525083604083015260806060830152615f566080830184615484565b9695505050505050565b600060208284031215615f7257600080fd5b815161252a81615415565b634e487b7160e01b600052603160045260246000fdfea264697066735822122042c1130d2195b44758719da073a973a8bb630f97dfe30aeaf62045a8edb5d4c464736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000058a15701ed1ad95bba625a05f41e50dce62aa14e00000000000000000000000082ced323fae774d7aedf822724be5cd1c58548c4
-----Decoded View---------------
Arg [0] : _buddyCoreAddr (address): 0x58a15701ED1aD95BBa625A05f41e50dCE62aA14e
Arg [1] : _gooContractAddr (address): 0x82cED323FaE774d7aEdf822724BE5cd1C58548c4
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000058a15701ed1ad95bba625a05f41e50dce62aa14e
Arg [1] : 00000000000000000000000082ced323fae774d7aedf822724be5cd1c58548c4
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in POL
Multichain Portfolio | 32 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.