Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,471 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Feed | 41909863 | 594 days ago | IN | 0 POL | 0.29144005 | ||||
Feed | 41257794 | 611 days ago | IN | 0 POL | 0.09080319 | ||||
Feed | 39994993 | 644 days ago | IN | 0 POL | 0.08879306 | ||||
Feed | 39994966 | 644 days ago | IN | 0 POL | 0.08571018 | ||||
Feed | 39994944 | 644 days ago | IN | 0 POL | 0.07551288 | ||||
Feed | 39994922 | 644 days ago | IN | 0 POL | 0.05909391 | ||||
Feed | 39994905 | 644 days ago | IN | 0 POL | 0.05585868 | ||||
Feed | 39994886 | 644 days ago | IN | 0 POL | 0.05198415 | ||||
Upgrade | 39786983 | 649 days ago | IN | 0 POL | 0.0320273 | ||||
Upgrade | 39786957 | 649 days ago | IN | 0 POL | 0.01810878 | ||||
Feed Egg | 39786940 | 649 days ago | IN | 0 POL | 0.02167781 | ||||
Feed | 39786916 | 649 days ago | IN | 0 POL | 0.05684417 | ||||
Feed Egg | 38227754 | 690 days ago | IN | 0 POL | 0.06859218 | ||||
Fuse | 38227719 | 690 days ago | IN | 0 POL | 0.01990159 | ||||
Fuse | 38227703 | 690 days ago | IN | 0 POL | 0.01992096 | ||||
Fuse | 38227683 | 690 days ago | IN | 0 POL | 0.0198342 | ||||
Fuse | 38227660 | 690 days ago | IN | 0 POL | 0.0186483 | ||||
Fuse | 38227646 | 690 days ago | IN | 0 POL | 0.01924219 | ||||
Fuse | 38117129 | 693 days ago | IN | 0 POL | 0.01673002 | ||||
Feed | 38117050 | 693 days ago | IN | 0 POL | 0.06337745 | ||||
Feed | 38117039 | 693 days ago | IN | 0 POL | 0.06138348 | ||||
Feed | 38117018 | 693 days ago | IN | 0 POL | 0.06738003 | ||||
Feed | 37994166 | 695 days ago | IN | 0 POL | 0.10486611 | ||||
Feed | 37961765 | 696 days ago | IN | 0 POL | 0.03922883 | ||||
Feed | 37931126 | 697 days ago | IN | 0 POL | 0.03018806 |
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
[{"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
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.