More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 38 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Safe Transfer Fr... | 16610565 | 751 days ago | IN | 0 ETH | 0.00134735 | ||||
Set Approval For... | 14169391 | 1119 days ago | IN | 0 ETH | 0.00369705 | ||||
Pickup Rewards | 13885378 | 1163 days ago | IN | 0 ETH | 0.00155274 | ||||
Withdraw | 13514015 | 1221 days ago | IN | 0 ETH | 0.00885562 | ||||
Set Approval For... | 13452182 | 1231 days ago | IN | 0 ETH | 0.00331938 | ||||
Attack | 13397429 | 1240 days ago | IN | 0.1 ETH | 0.0432875 | ||||
Attack | 13391569 | 1241 days ago | IN | 0.1 ETH | 0.03297826 | ||||
Attack | 13390670 | 1241 days ago | IN | 0.1 ETH | 0.02713534 | ||||
Attack | 13387623 | 1241 days ago | IN | 0.1 ETH | 0.03611762 | ||||
Attack | 13387584 | 1241 days ago | IN | 0.1 ETH | 0.03589239 | ||||
Attack | 13385726 | 1242 days ago | IN | 0.1 ETH | 0.0510189 | ||||
Attack | 13385716 | 1242 days ago | IN | 0.1 ETH | 0.03761117 | ||||
Attack | 13385551 | 1242 days ago | IN | 0 ETH | 0.00266371 | ||||
Attack | 13385474 | 1242 days ago | IN | 0.1 ETH | 0.04399067 | ||||
Attack | 13385462 | 1242 days ago | IN | 0.1 ETH | 0.04709238 | ||||
Attack | 13385451 | 1242 days ago | IN | 0.1 ETH | 0.03749292 | ||||
Attack | 13385374 | 1242 days ago | IN | 0.1 ETH | 0.02798133 | ||||
Attack | 13385199 | 1242 days ago | IN | 0.1 ETH | 0.03084262 | ||||
Attack | 13384929 | 1242 days ago | IN | 0.1 ETH | 0.02604149 | ||||
Attack | 13384903 | 1242 days ago | IN | 0.1 ETH | 0.04425857 | ||||
Attack | 13384521 | 1242 days ago | IN | 0.1 ETH | 0.03163325 | ||||
Attack | 13384516 | 1242 days ago | IN | 0.1 ETH | 0.02682311 | ||||
Attack | 13384508 | 1242 days ago | IN | 0.1 ETH | 0.03622296 | ||||
Attack | 13384488 | 1242 days ago | IN | 0.1 ETH | 0.02653585 | ||||
Attack | 13384483 | 1242 days ago | IN | 0.1 ETH | 0.02800224 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
13514015 | 1221 days ago | 2.9 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Quest
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.8.7; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol"; import "./interfaces/ILoot.sol"; import "./interfaces/ILootComponents.sol"; import "./Base64.sol"; contract Quest is ERC721Enumerable, VRFConsumerBase, Ownable, ReentrancyGuard { using Counters for Counters.Counter; Counters.Counter public currentTurn; event GameStarted(); event RequestedRandomness(uint16 turnNumber, bytes32 requestId); event RandomnessReceived( bytes32 requestId, uint16 turnNumber, uint256 randomness ); event Attack( uint16 turnNumber, uint16 lootId, uint8 damageDealt, bool attackModifier, bool supportModifier, bool addedSupportModifier, uint32 dragonHP ); event DragonSlain(); event AGLDDistributed(); event AGLDClaimed(uint16 turnNumber, uint256 amount); struct Turn { uint8 damageDealt; uint16 turnNumber; uint16 lootId; uint16 cumulativeTurnsPlayed; uint32 cumulativeDamageDealt; uint32 dragonHP; bool hadAttackModifier; bool hadSupportModifier; bool addedSupportModifier; bool dragonSlayed; address attacker; } struct AttackRecord { uint32 cumulativeDamageDealt; uint32 cumulativeSupportDamageDealt; uint16 turnsPlayedByAttacker; uint16 lastTurn; } uint256 public constant price = 100000000000000000; // 0.1 ETH uint256 public constant agldPrice = 100000000000000000000; // 100 AGLD uint256 public constant MIN_POT_SIZE = 400000 ether; // 400k AGLD uint8 public constant MIN_DAMAGE = 25; uint8 public constant MAX_DAMAGE = 200; uint8 public constant ATTACK_MODIFIER = 25; // MIN_DAMAGE * 0.25; save some gas uint8 public constant SUPPORT_MODIFIER = 50; // MIN_DAMAGE * 0.5 uint32 public dragonStartingHP; uint32 public dragonCurrentHP; bool public vrfLock = true; bool public distributed = false; uint8[4] private numWinners = [100, 40, 7, 1]; uint256[4] private drops = [ uint256(1000 ether), uint256(2500 ether), uint256(10000 ether), uint256(100000 ether) ]; address public lootContractAddress; address public lootComponentsContractAddress; address public agldContractAddress; ILoot public lootContract; ILootComponents public lootComponentsContract; IERC20 public agldContract; bytes32 private s_keyHash; uint256 private s_fee; address public mostDamageAddress; address public mostSupportAddress; address public dragonSlayerAddress; mapping(uint16 => Turn) private _turnsPlayed; mapping(address => AttackRecord) private _attackRecords; mapping(bytes32 => uint16) public requestIdToTurn; mapping(bytes32 => uint256) public requestIdToRandomNumber; mapping(uint16 => uint256) public turnToRandomNumber; mapping(uint16 => uint256) public turnToAGLDAvailable; mapping(uint16 => bool) public turnToAGLDClaimed; constructor( address vrfCoordinator, address link, bytes32 keyHash, uint256 fee, uint32 startHP, address _lootContractAddress, address _lootComponentsContractAddress, address _agldContractAddress ) ERC721("Quest (for Loot)", "QUEST") VRFConsumerBase(vrfCoordinator, link) Ownable() { lootContractAddress = _lootContractAddress; lootComponentsContractAddress = _lootComponentsContractAddress; agldContractAddress = _agldContractAddress; lootContract = ILoot(lootContractAddress); lootComponentsContract = ILootComponents(lootComponentsContractAddress); agldContract = IERC20(agldContractAddress); dragonStartingHP = startHP; dragonCurrentHP = dragonStartingHP; s_keyHash = keyHash; s_fee = fee; } function getRandomNumber() internal returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK"); uint16 turnNumber = uint16(currentTurn.current()); vrfLock = true; requestId = requestRandomness(s_keyHash, s_fee); requestIdToTurn[requestId] = turnNumber; emit RequestedRandomness(turnNumber, requestId); return requestId; } function seedFirstRandomNumber() external onlyOwner returns (bytes32) { require(vrfLock == true, "Not locked"); require(currentTurn.current() == 0, "Already started turns"); emit GameStarted(); return getRandomNumber(); } function seedFulfillRandomness(bytes32 requestId, uint256 randomness) external onlyOwner { fulfillRandomness(requestId, randomness); } function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { uint16 turnNumber = requestIdToTurn[requestId]; requestIdToRandomNumber[requestId] = randomness; turnToRandomNumber[turnNumber] = randomness; vrfLock = false; emit RandomnessReceived(requestId, turnNumber, randomness); } function supportModifierWasAdded( uint16 previousTurn, bool addedSupportModifier ) internal view returns (bool) { bool supportModifier = false; if (previousTurn > 0 && addedSupportModifier == false) { // Don't let Divines stack attacks (, , , , , , , , , supportModifier, , ) = getTurn(previousTurn); } return supportModifier; } function associateTurnWithAttacker( address attacker, uint16 lootId, uint16 turnNumber, uint8 damageDealt, bool attackModifier, bool supportModifier, bool addedSupportModifier ) internal { Turn storage t = _turnsPlayed[turnNumber]; AttackRecord storage a = _attackRecords[attacker]; if (mostDamageAddress == address(0)) { mostDamageAddress = attacker; } AttackRecord storage mostDamage = _attackRecords[mostDamageAddress]; a.cumulativeDamageDealt += damageDealt; a.lastTurn = turnNumber; a.turnsPlayedByAttacker += 1; if (a.cumulativeDamageDealt > mostDamage.cumulativeDamageDealt) { mostDamageAddress = attacker; } t.turnNumber = turnNumber; t.attacker = attacker; t.lootId = lootId; t.damageDealt = damageDealt; t.cumulativeDamageDealt = a.cumulativeDamageDealt; t.cumulativeTurnsPlayed = a.turnsPlayedByAttacker; t.dragonHP = dragonCurrentHP; t.hadAttackModifier = attackModifier; t.hadSupportModifier = supportModifier; t.addedSupportModifier = addedSupportModifier; t.dragonSlayed = dragonCurrentHP == 0; if (t.dragonSlayed == true) { dragonSlayerAddress = attacker; } } function associateSupportDamageWithAttacker( uint16 turnNumber, uint8 damageDealt, bool supportModifier ) internal { Turn storage t = _turnsPlayed[turnNumber]; AttackRecord storage a = _attackRecords[t.attacker]; if (mostSupportAddress == address(0)) { mostSupportAddress = t.attacker; } AttackRecord storage mostSupport = _attackRecords[mostSupportAddress]; if (supportModifier == true && t.addedSupportModifier == true) { a.cumulativeSupportDamageDealt += damageDealt; if ( a.cumulativeSupportDamageDealt > mostSupport.cumulativeSupportDamageDealt ) { mostSupportAddress = t.attacker; } } } function awardAGLDToTurn(uint16 turnNumber, uint256 agldAmount) internal { turnToAGLDAvailable[turnNumber] += agldAmount; } function attack(uint16 lootId) external payable nonReentrant { require(dragonCurrentHP > 0, "Dragon is slain"); require(vrfLock == false, "Waiting for VRF to return"); require(lootId > 0 && lootId <= 8000, "Invalid ID"); require(msg.sender == lootContract.ownerOf(lootId), "Not loot owner"); require(price <= msg.value, "Insufficient Ether"); require( agldPrice <= agldContract.allowance(msg.sender, address(this)), "AGLD spend not approved" ); require( agldContract.transferFrom(msg.sender, address(this), agldPrice), "AGLD could not be transferred" ); uint16 previousTurn = uint16(currentTurn.current()); currentTurn.increment(); uint16 newTurn = uint16(currentTurn.current()); bool attackModifier = hasAttackModifier(lootId); bool addedSupportModifier = hasSupportModifier(lootId); bool supportModifier = supportModifierWasAdded( previousTurn, addedSupportModifier ); uint16 turnModulo = newTurn % 512; uint8 damageDealt = getAttackDamage( newTurn, attackModifier, supportModifier, turnModulo ); dragonCurrentHP = dragonCurrentHP - damageDealt; associateTurnWithAttacker( _msgSender(), lootId, newTurn, damageDealt, attackModifier, supportModifier, addedSupportModifier ); associateSupportDamageWithAttacker( previousTurn, damageDealt, supportModifier ); emit Attack( newTurn, lootId, damageDealt, attackModifier, supportModifier, addedSupportModifier, dragonCurrentHP ); if (dragonCurrentHP > 0 && turnModulo == 0) { getRandomNumber(); // get every 512 turns or on first turn } if (dragonCurrentHP == 0) { emit DragonSlain(); getRandomNumber(); // trigger the final loot drop } _safeMint(_msgSender(), newTurn); } function ownerTriggersDistributeLoot() external onlyOwner { // final distribution is expensive // failsafe in case dragon slayer doesn't do it require(dragonCurrentHP == 0, "Dragon is not slain"); require(vrfLock == false, "Waiting for VRF to return"); distributeLoot(); } function dragonSlayerTriggersDistributeLoot() external { require(dragonCurrentHP == 0, "Dragon is not slain"); require(vrfLock == false, "Waiting for VRF to return"); AttackRecord storage dragonSlayer = _attackRecords[dragonSlayerAddress]; require( _msgSender() == ownerOf(dragonSlayer.lastTurn), "Must be dragon slayer" ); distributeLoot(); } function distributeLoot() private { require(distributed == false, "Already distributed"); require(dragonCurrentHP == 0, "Dragon is not slain"); uint256 agldBalance = agldContract.balanceOf(address(this)); require(agldBalance >= MIN_POT_SIZE, "Not enough AGLD"); uint16 j = 0; uint16 winner; uint16 turnNumber = uint16(currentTurn.current()); uint256 amountDistributed = 0; // 1. Reward the dragon slayer. AttackRecord storage dragonSlayer = _attackRecords[dragonSlayerAddress]; awardAGLDToTurn(dragonSlayer.lastTurn, 10000 ether); amountDistributed += 10000 ether; // 2. Reward the attacker who dealt the most damage. AttackRecord storage mostDamage = _attackRecords[mostDamageAddress]; awardAGLDToTurn(mostDamage.lastTurn, 10000 ether); amountDistributed += 10000 ether; // 3. Reward the attacker who provided the most support. if (mostSupportAddress != address(0)) { AttackRecord storage mostSupport = _attackRecords[mostSupportAddress]; awardAGLDToTurn(mostSupport.lastTurn, 10000 ether); amountDistributed += 10000 ether; } // 4. Get the latest random seed number uint256 randomResult = turnToRandomNumber[turnNumber]; // 5. Award 1,000 AGLD to 100 turns uint8 upperLimit = 0; for (uint8 i = 0; i < numWinners.length; i++) { upperLimit += numWinners[i]; for (j; j < upperLimit; j++) { winner = uint16((random(j, randomResult) % turnNumber) + 1); awardAGLDToTurn(winner, drops[i]); amountDistributed += drops[i]; } } // 8. Find the remaining balance uint256 remainingBalance = agldBalance - amountDistributed; // 9. Award half of the remaining balance to the slayer & grand prize winner if (remainingBalance > 0) { uint256 dragonSlayerAdditional = remainingBalance / 2; uint256 grandPrizeAdditional = remainingBalance - dragonSlayerAdditional; awardAGLDToTurn(dragonSlayer.lastTurn, dragonSlayerAdditional); awardAGLDToTurn(winner, grandPrizeAdditional); } distributed = true; emit AGLDDistributed(); } function pickupReward(uint16 turnNumber) external nonReentrant { require(_msgSender() == ownerOf(turnNumber), "Must own turn"); require(turnToAGLDAvailable[turnNumber] > 0, "No AGLD to claim"); require(turnToAGLDClaimed[turnNumber] == false, "AGLD already claimed"); agldContract.transfer(_msgSender(), turnToAGLDAvailable[turnNumber]); turnToAGLDClaimed[turnNumber] = true; emit AGLDClaimed(turnNumber, turnToAGLDAvailable[turnNumber]); } function pickupRewards() external nonReentrant { uint256 balance = balanceOf(_msgSender()); require(balance > 0, "Must own at least 1 turn"); for (uint256 i = 0; i < balance; i++) { uint16 turnNumber = uint16(tokenOfOwnerByIndex(_msgSender(), i)); if (turnToAGLDAvailable[turnNumber] > 0 && turnToAGLDClaimed[turnNumber] == false) { agldContract.transfer(_msgSender(), turnToAGLDAvailable[turnNumber]); turnToAGLDClaimed[turnNumber] = true; emit AGLDClaimed(turnNumber, turnToAGLDAvailable[turnNumber]); } } } function withdraw() external onlyOwner { payable(owner()).transfer(address(this).balance); LINK.transfer(payable(owner()), LINK.balanceOf(address(this))); } /* * * Note: damage is capped to the ceiling amount. I realize this isn't * ideal, but given the complexities involved in ensuring we have * sufficient AGLD to distribute, I did this to simplify the function. * Yes, I also realize this means we mint more NFTs. I promise to make it * up to everyone. * */ function getAttackDamage( uint16 turnNumber, bool attackModifier, bool supportModifier, uint16 turnModulo ) private view returns (uint8) { uint8 damageModifier = (attackModifier == true ? ATTACK_MODIFIER : 0) + (supportModifier == true ? SUPPORT_MODIFIER : 0); uint8 floor = damageModifier + MIN_DAMAGE; uint8 ceiling = MAX_DAMAGE - floor; uint16 randomIndex = turnNumber - turnModulo; uint256 randomResult = turnToRandomNumber[randomIndex]; uint8 damageDealt = uint8( (random(turnNumber, randomResult) % ceiling) + floor ); if (damageDealt > dragonCurrentHP) { damageDealt = uint8(dragonCurrentHP); } return damageDealt; } function random(uint256 number, uint256 randomResult) private view returns (uint256) { return uint256( keccak256( abi.encodePacked( block.difficulty, block.timestamp, block.number, randomResult, number ) ) ); } function getAttackRecord(address attacker) public view returns ( uint32 cumulativeDamageDealt, uint32 cumulativeSupportDamageDealt, uint16 turnsPlayed, uint16 lastTurn ) { require(attacker != address(0), "Attack record query for zero address"); AttackRecord storage a = _attackRecords[attacker]; cumulativeDamageDealt = a.cumulativeDamageDealt; cumulativeSupportDamageDealt = a.cumulativeSupportDamageDealt; turnsPlayed = a.turnsPlayedByAttacker; lastTurn = a.lastTurn; } function getTurn(uint16 turnNumber) public view returns ( address attacker, uint16 lootId, uint8 damageDealt, uint32 cumulativeDamageDealtByAttacker, uint16 cumulativeTurnsPlayedByAttacker, uint32 dragonHP, uint256 agldAvailable, bool hadAttackModifier, bool hadSupportModifier, bool addedSupportModifier, bool agldClaimed, bool dragonSlayed ) { require(turnNumber > 0, "Turn number has to be greater than 0"); Turn storage t = _turnsPlayed[turnNumber]; attacker = t.attacker; lootId = t.lootId; damageDealt = t.damageDealt; cumulativeDamageDealtByAttacker = t.cumulativeDamageDealt; cumulativeTurnsPlayedByAttacker = t.cumulativeTurnsPlayed; dragonHP = t.dragonHP; agldAvailable = turnToAGLDAvailable[turnNumber]; hadAttackModifier = t.hadAttackModifier; hadSupportModifier = t.hadSupportModifier; addedSupportModifier = t.addedSupportModifier; agldClaimed = turnToAGLDClaimed[turnNumber]; dragonSlayed = t.dragonSlayed; } function hasAttackModifier(uint256 lootId) public view returns (bool) { require(lootId > 0 && lootId <= 8000, "Invalid ID"); return lootComponentsContract.chestComponents(lootId)[0] == 6 || lootComponentsContract.headComponents(lootId)[0] == 6 || lootComponentsContract.waistComponents(lootId)[0] == 6 || lootComponentsContract.footComponents(lootId)[0] == 6 || lootComponentsContract.handComponents(lootId)[0] == 6; } function hasSupportModifier(uint256 lootId) public view returns (bool) { require(lootId > 0 && lootId <= 8000, "Invalid ID"); return lootComponentsContract.chestComponents(lootId)[0] == 0; } function isDragonSlain() public view returns (bool) { return dragonCurrentHP == 0; } function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT license // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } function generateCard(uint16 turnNumber) internal view returns (string memory) { (, , uint256 damageDealt, , , uint256 dragonHP, , , , , , ) = getTurn( turnNumber ); return string( abi.encodePacked( '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: #FFFCFC; font-family: monospace; font-size: 14px; } .title { fill: #FFFCFC; font-family: monospace; font-size: 24px; text-anchor: middle; dominant-baseline: middle; }</style><rect width="100%" height="100%" fill="#003F63" /><text x="175" y="35" class="title">QUESTS FOR LOOT</text><text x="30" y="85" class="base">Turn ', toString(turnNumber), '</text><text x="30" y="115" class="base">Damage: ', toString(damageDealt), ' HP</text><text x="30" y="135" class="base">Remaining: ', toString(dragonHP) ) ); } function generateAttackerInfo(uint16 turnNumber) internal view returns (string memory) { ( , uint16 lootId, , uint32 cumulativeDamageDealt, uint32 turnsPlayed, , , , , , , ) = getTurn(turnNumber); return string( abi.encodePacked( ' HP</text><text x="30" y="155" class="base">Loot Bag: #', toString(lootId), '</text><text x="30" y="175" class="base">Turns Played: ', toString(turnsPlayed), '</text><text x="30" y="195" class="base">Total Damage: ', toString(cumulativeDamageDealt) ) ); } function generateBoosts(uint16 turnNumber) internal view returns (string memory) { ( , , , , , , , bool attackModifier, bool supportModifier, bool addedSupportModifier, , ) = getTurn(turnNumber); return string( abi.encodePacked( '</text><text x="30" y="225" class="base">Damage Boost: ', attackModifier ? "Yes" : "No", '</text><text x="30" y="245" class="base">Support Boost: ', supportModifier ? "Yes" : "No", '</text><text x="30" y="265" class="base">Provided Support: ', addedSupportModifier ? "Yes" : "No", '</text><text x="30" y="295" class="base">' ) ); } function generateUniqueTraits(uint16 turnNumber) internal view returns (string memory) { ( , , , , , , uint256 agldAvailable, , , , bool agldClaimed, bool dragonSlayed ) = getTurn(turnNumber); return string( abi.encodePacked( turnNumber == 1 ? "First strike!" : dragonSlayed ? "You slayed the dragon!" : "The dragon lives...", '</text><text x="30" y="315" class="base">', agldAvailable > 0 ? (agldClaimed == true ? "Claimed: " : "Available: ") : "", agldAvailable > 0 ? toString(agldAvailable / 1 ether) : "", agldAvailable > 0 ? " AGLD" : "", '</text><rect x="322.2" y="325.2" transform="matrix(0.7342 -0.6789 0.6789 0.7342 -136.3816 307.9781)" fill="#F2B138" width="5.9" height="5.9"/><rect x="326.6" y="321.2" transform="matrix(0.7342 -0.6789 0.6789 0.7342 -132.5075 309.8563)" fill="#B78330" width="5.9" height="5.9"/><rect x="326.2" y="329.6" transform="matrix(0.7342 -0.6789 0.6789 0.7342 -138.2598 311.8521)" fill="#B78330" width="5.9" height="5.9"/><rect x="330.6" y="325.6" transform="matrix(0.7342 -0.6789 0.6789 0.7342 -134.3857 313.7304)" fill="#F2B138" width="5.9" height="5.9"/></svg>' ) ); } function generateOpenSeaAttributes(uint16 turnNumber) internal view returns (string memory) { ( , uint16 lootId, uint8 damageDealt, uint32 cumulativeDamageDealtByAttacker, uint16 cumulativeTurnsPlayedByAttacker, uint32 dragonHP, uint256 agldAvailable, bool hadAttackModifier, bool hadSupportModifier, bool addedSupportModifier, bool agldClaimed, bool dragonSlayed ) = getTurn(turnNumber); string[3] memory parts; parts[0] = string( abi.encodePacked( '{"trait_type": "Loot", "value": "', toString(lootId), '"},{"trait_type": "Damage Dealt", "value": ', toString(damageDealt), '},{"trait_type": "Cumulative Damage Dealt", "display_type": "number", "value": ', toString(cumulativeDamageDealtByAttacker), '},{"trait_type": "Cumulative Turns Played", "display_type": "number", "value": ', toString(cumulativeTurnsPlayedByAttacker) ) ); parts[1] = string( abi.encodePacked( '},{"trait_type": "Dragon HP", "value": ', toString(dragonHP), '},{"trait_type": "AGLD Available", "display_type": "number", "value": ', toString(agldAvailable / 1 ether), '},{"trait_type": "Damage Boost", "display_type": "boost_number", "value": ', hadAttackModifier ? toString(ATTACK_MODIFIER) : toString(0), '},{"trait_type": "Support Boost", "display_type": "boost_number", "value": ', hadSupportModifier ? toString(SUPPORT_MODIFIER) : toString(0) ) ); parts[2] = string( abi.encodePacked( '},{"trait_type": "Provided Support", "value": ', addedSupportModifier ? '"Yes"' : '"No"', '},{"trait_type": "AGLD Claimed", "value": ', agldClaimed ? '"Yes"' : '"No"', '},{"trait_type": "Dragon Slayer", "value": ', dragonSlayed ? '"Yes"' : '"No"', "}" ) ); string memory output = string( abi.encodePacked(parts[0], parts[1], parts[2]) ); return output; } function tokenURI(uint256 tn) public view override returns (string memory) { string[4] memory parts; uint16 turnNumber = uint16(tn); parts[0] = generateCard(turnNumber); parts[1] = generateAttackerInfo(turnNumber); parts[2] = generateBoosts(turnNumber); parts[3] = generateUniqueTraits(turnNumber); string memory output = string( abi.encodePacked(parts[0], parts[1], parts[2], parts[3]) ); string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "Turn ', toString(turnNumber), '", "attributes": [', generateOpenSeaAttributes(turnNumber), '], "description": "Quests for Loot are battle records stored on-chain for a MUD to slay a dragon that\'s ravaging a village. Players must work together to defeat it and reap the rewards!", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(output)), '"}' ) ) ) ); output = string( abi.encodePacked("data:application/json;base64,", json) ); return output; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/LinkTokenInterface.sol"; import "./VRFRequestIDBase.sol"; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constuctor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator, _link) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash), and have told you the minimum LINK * @dev price for VRF service. Make sure your contract has sufficient LINK, and * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you * @dev want to generate randomness from. * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomness method. * * @dev The randomness argument to fulfillRandomness is the actual random value * @dev generated from your seed. * * @dev The requestId argument is generated from the keyHash and the seed by * @dev makeRequestId(keyHash, seed). If your contract could have concurrent * @dev requests open, you can use the requestId to track which seed is * @dev associated with which randomness. See VRFRequestIDBase.sol for more * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously.) * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. (Which is critical to making unpredictable randomness! See the * @dev next section.) * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the ultimate input to the VRF is mixed with the block hash of the * @dev block in which the request is made, user-provided seeds have no impact * @dev on its economic security properties. They are only included for API * @dev compatability with previous versions of this contract. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. */ abstract contract VRFConsumerBase is VRFRequestIDBase { /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBase expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomness the VRF output */ function fulfillRandomness( bytes32 requestId, uint256 randomness ) internal virtual; /** * @dev In order to keep backwards compatibility we have kept the user * seed field around. We remove the use of it because given that the blockhash * enters later, it overrides whatever randomness the used seed provides. * Given that it adds no security, and can easily lead to misunderstandings, * we have removed it from usage and can now provide a simpler API. */ uint256 constant private USER_SEED_PLACEHOLDER = 0; /** * @notice requestRandomness initiates a request for VRF output given _seed * * @dev The fulfillRandomness method receives the output, once it's provided * @dev by the Oracle, and verified by the vrfCoordinator. * * @dev The _keyHash must already be registered with the VRFCoordinator, and * @dev the _fee must exceed the fee specified during registration of the * @dev _keyHash. * * @dev The _seed parameter is vestigial, and is kept only for API * @dev compatibility with older versions. It can't *hurt* to mix in some of * @dev your own randomness, here, but it's not necessary because the VRF * @dev oracle will mix the hash of the block containing your request into the * @dev VRF seed it ultimately uses. * * @param _keyHash ID of public key against which randomness is generated * @param _fee The amount of LINK to send with the request * * @return requestId unique ID for this request * * @dev The returned requestId can be used to distinguish responses to * @dev concurrent requests. It is passed as the first argument to * @dev fulfillRandomness. */ function requestRandomness( bytes32 _keyHash, uint256 _fee ) internal returns ( bytes32 requestId ) { LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER)); // This is the seed passed to VRFCoordinator. The oracle will mix this with // the hash of the block containing this request to obtain the seed/input // which is finally passed to the VRF cryptographic machinery. uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]); // nonces[_keyHash] must stay in sync with // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). // This provides protection against the user repeating their input seed, // which would result in a predictable/duplicate output, if multiple such // requests appeared in the same block. nonces[_keyHash] = nonces[_keyHash] + 1; return makeRequestId(_keyHash, vRFSeed); } LinkTokenInterface immutable internal LINK; address immutable private vrfCoordinator; // Nonces for each VRF key from which randomness has been requested. // // Must stay in sync with VRFCoordinator[_keyHash][this] mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces; /** * @param _vrfCoordinator address of VRFCoordinator contract * @param _link address of LINK token contract * * @dev https://docs.chain.link/docs/link-token-contracts */ constructor( address _vrfCoordinator, address _link ) { vrfCoordinator = _vrfCoordinator; LINK = LinkTokenInterface(_link); } // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomness( bytes32 requestId, uint256 randomness ) external { require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); fulfillRandomness(requestId, randomness); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract VRFRequestIDBase { /** * @notice returns the seed which is actually input to the VRF coordinator * * @dev To prevent repetition of VRF output due to repetition of the * @dev user-supplied seed, that seed is combined in a hash with the * @dev user-specific nonce, and the address of the consuming contract. The * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in * @dev the final seed, but the nonce does protect against repetition in * @dev requests which are included in a single block. * * @param _userSeed VRF seed input provided by user * @param _requester Address of the requesting contract * @param _nonce User-specific nonce at the time of the request */ function makeVRFInputSeed( bytes32 _keyHash, uint256 _userSeed, address _requester, uint256 _nonce ) internal pure returns ( uint256 ) { return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); } /** * @notice Returns the id for this request * @param _keyHash The serviceAgreement ID to be used for this request * @param _vRFInputSeed The seed to be passed directly to the VRF * @return The id for this request * * @dev Note that _vRFInputSeed is not the seed passed by the consuming * @dev contract, but the one generated by makeVRFInputSeed */ function makeRequestId( bytes32 _keyHash, uint256 _vRFInputSeed ) internal pure returns ( bytes32 ) { return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance( address owner, address spender ) external view returns ( uint256 remaining ); function approve( address spender, uint256 value ) external returns ( bool success ); function balanceOf( address owner ) external view returns ( uint256 balance ); function decimals() external view returns ( uint8 decimalPlaces ); function decreaseApproval( address spender, uint256 addedValue ) external returns ( bool success ); function increaseApproval( address spender, uint256 subtractedValue ) external; function name() external view returns ( string memory tokenName ); function symbol() external view returns ( string memory tokenSymbol ); function totalSupply() external view returns ( uint256 totalTokensIssued ); function transfer( address to, uint256 value ) external returns ( bool success ); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns ( bool success ); function transferFrom( address from, address to, uint256 value ) external returns ( bool success ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.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() { _setOwner(_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 { _setOwner(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"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT 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 { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `_data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _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); } /** * @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); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); 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); } /** * @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 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 {} }
// SPDX-License-Identifier: MIT 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 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 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 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 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (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 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 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 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 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 pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
/// [MIT License] /// @title Base64 /// @notice Provides a function for encoding some bytes in base64 /// @author Brecht Devos <[email protected]> library Base64 { bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /// @notice Encodes some bytes to the base64 representation function encode(bytes memory data) internal pure returns (string memory) { uint256 len = data.length; if (len == 0) return ""; // multiply by 4/3 rounded up uint256 encodedLen = 4 * ((len + 2) / 3); // Add some extra buffer at the end bytes memory result = new bytes(encodedLen + 32); bytes memory table = TABLE; assembly { let tablePtr := add(table, 1) let resultPtr := add(result, 32) for { let i := 0 } lt(i, len) { } { i := add(i, 3) let input := and(mload(add(data, i)), 0xffffff) let out := mload(add(tablePtr, and(shr(18, input), 0x3F))) out := shl(8, out) out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF)) out := shl(8, out) out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF)) out := shl(8, out) out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF)) out := shl(224, out) mstore(resultPtr, out) resultPtr := add(resultPtr, 4) } switch mod(len, 3) case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) } case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) } mstore(result, encodedLen) } return string(result); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; interface ILoot { function ownerOf(uint256 tokenId) external view returns (address); function getWeapon(uint256 tokenId) external view returns (string calldata); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; interface ILootComponents { function weaponComponents(uint256 tokenId) external view returns (uint256[5] memory); function waistComponents(uint256 tokenId) external view returns (uint256[5] memory); function ringComponents(uint256 tokenId) external view returns (uint256[5] memory); function neckComponents(uint256 tokenId) external view returns (uint256[5] memory); function headComponents(uint256 tokenId) external view returns (uint256[5] memory); function handComponents(uint256 tokenId) external view returns (uint256[5] memory); function footComponents(uint256 tokenId) external view returns (uint256[5] memory); function chestComponents(uint256 tokenId) external view returns (uint256[5] memory); // uint256[5] => // [0] = Item ID // [1] = Suffix ID (0 for none) // [2] = Name Prefix ID (0 for none) // [3] = Name Suffix ID (0 for none) // [4] = Augmentation (0 = false, 1 = true) }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"vrfCoordinator","type":"address"},{"internalType":"address","name":"link","type":"address"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"uint256","name":"fee","type":"uint256"},{"internalType":"uint32","name":"startHP","type":"uint32"},{"internalType":"address","name":"_lootContractAddress","type":"address"},{"internalType":"address","name":"_lootComponentsContractAddress","type":"address"},{"internalType":"address","name":"_agldContractAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"turnNumber","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"AGLDClaimed","type":"event"},{"anonymous":false,"inputs":[],"name":"AGLDDistributed","type":"event"},{"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":false,"internalType":"uint16","name":"turnNumber","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"lootId","type":"uint16"},{"indexed":false,"internalType":"uint8","name":"damageDealt","type":"uint8"},{"indexed":false,"internalType":"bool","name":"attackModifier","type":"bool"},{"indexed":false,"internalType":"bool","name":"supportModifier","type":"bool"},{"indexed":false,"internalType":"bool","name":"addedSupportModifier","type":"bool"},{"indexed":false,"internalType":"uint32","name":"dragonHP","type":"uint32"}],"name":"Attack","type":"event"},{"anonymous":false,"inputs":[],"name":"DragonSlain","type":"event"},{"anonymous":false,"inputs":[],"name":"GameStarted","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":"bytes32","name":"requestId","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"turnNumber","type":"uint16"},{"indexed":false,"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"RandomnessReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"turnNumber","type":"uint16"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"RequestedRandomness","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"ATTACK_MODIFIER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_DAMAGE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_DAMAGE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_POT_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUPPORT_MODIFIER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"agldContract","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"agldContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"agldPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"uint16","name":"lootId","type":"uint16"}],"name":"attack","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTurn","outputs":[{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dragonCurrentHP","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dragonSlayerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dragonSlayerTriggersDistributeLoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dragonStartingHP","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"attacker","type":"address"}],"name":"getAttackRecord","outputs":[{"internalType":"uint32","name":"cumulativeDamageDealt","type":"uint32"},{"internalType":"uint32","name":"cumulativeSupportDamageDealt","type":"uint32"},{"internalType":"uint16","name":"turnsPlayed","type":"uint16"},{"internalType":"uint16","name":"lastTurn","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"turnNumber","type":"uint16"}],"name":"getTurn","outputs":[{"internalType":"address","name":"attacker","type":"address"},{"internalType":"uint16","name":"lootId","type":"uint16"},{"internalType":"uint8","name":"damageDealt","type":"uint8"},{"internalType":"uint32","name":"cumulativeDamageDealtByAttacker","type":"uint32"},{"internalType":"uint16","name":"cumulativeTurnsPlayedByAttacker","type":"uint16"},{"internalType":"uint32","name":"dragonHP","type":"uint32"},{"internalType":"uint256","name":"agldAvailable","type":"uint256"},{"internalType":"bool","name":"hadAttackModifier","type":"bool"},{"internalType":"bool","name":"hadSupportModifier","type":"bool"},{"internalType":"bool","name":"addedSupportModifier","type":"bool"},{"internalType":"bool","name":"agldClaimed","type":"bool"},{"internalType":"bool","name":"dragonSlayed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lootId","type":"uint256"}],"name":"hasAttackModifier","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"lootId","type":"uint256"}],"name":"hasSupportModifier","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isDragonSlain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootComponentsContract","outputs":[{"internalType":"contract ILootComponents","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootComponentsContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootContract","outputs":[{"internalType":"contract ILoot","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mostDamageAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mostSupportAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"ownerTriggersDistributeLoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"turnNumber","type":"uint16"}],"name":"pickupReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pickupRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToRandomNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToTurn","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"seedFirstRandomNumber","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"seedFulfillRandomness","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":"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":"tn","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":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"turnToAGLDAvailable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"turnToAGLDClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"turnToRandomNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vrfLock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
600e805461ffff60401b191668010000000000000000179055610140604052606460c0908152602860e0526007610100526001610120526200004690600f90600462000260565b506040518060800160405280683635c9adc5dea00000815260200168878678326eac900000815260200169021e19e0c9bab2400000815260200169152d02c7e14af68000008152506010906004620000a0929190620002fa565b50348015620000ae57600080fd5b506040516200636e3803806200636e833981016040819052620000d191620003db565b604080518082018252601081526f51756573742028666f72204c6f6f742960801b60208083019182528351808501909452600584526414555154d560da1b9084015281518b938b939290916200012a916000916200032b565b508051620001409060019060208401906200032b565b5050506001600160601b0319606092831b811660a052911b166080526200016e620001683390565b6200020e565b6001600c55601480546001600160a01b039485166001600160a01b03199182168117909255601580549486169482168517905560168054939095169281168317909455601780548516909117905560188054841690921790915560198054909216179055600e805464010000000063ffffffff9093169283026001600160401b0319909116909217919091179055601a91909155601b5550620004b89050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600183019183908215620002e85791602002820160005b83821115620002b757835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030262000277565b8015620002e65782816101000a81549060ff0219169055600101602081600001049283019260010302620002b7565b505b50620002f6929150620003a7565b5090565b8260048101928215620002e8579160200282015b82811115620002e85782518255916020019190600101906200030e565b82805462000339906200047b565b90600052602060002090601f0160209004810192826200035d5760008555620002e8565b82601f106200037857805160ff1916838001178555620002e8565b82800160010185558215620002e85791820182811115620002e85782518255916020019190600101906200030e565b5b80821115620002f65760008155600101620003a8565b80516001600160a01b0381168114620003d657600080fd5b919050565b600080600080600080600080610100898b031215620003f957600080fd5b6200040489620003be565b97506200041460208a01620003be565b96506040890151955060608901519450608089015163ffffffff811681146200043c57600080fd5b93506200044c60a08a01620003be565b92506200045c60c08a01620003be565b91506200046c60e08a01620003be565b90509295985092959890939650565b600181811c908216806200049057607f821691505b60208210811415620004b257634e487b7160e01b600052602260045260246000fd5b50919050565b60805160601c60a05160601c615e6e6200050060003960008181611e3d015261406c0152600081816115d40152818161162801528181612fda015261403d0152615e6e6000f3fe60806040526004361061038b5760003560e01c8063715018a6116101dc578063b128505b11610102578063deb61286116100a0578063f6a9e2011161006f578063f6a9e20114610b8d578063f6eac58f14610b0f578063f84b903e14610ba0578063fe89483614610bc157600080fd5b8063deb6128614610af8578063e53fb91014610b0f578063e985e9c514610b24578063f2fde38b14610b6d57600080fd5b8063c5ab60c2116100dc578063c5ab60c214610a7f578063c87b56dd14610aa6578063cde9729e14610ac6578063d095497814610ae357600080fd5b8063b128505b14610a0b578063b43be74514610a3b578063b88d4fde14610a5f57600080fd5b806394985ddd1161017a578063a22cb46511610149578063a22cb4651461096c578063a2c6188b1461098c578063a8af32e9146109be578063aa749dbf146109de57600080fd5b806394985ddd146108ee57806395d89b411461090e5780639bef920014610923578063a035b1fe1461095057600080fd5b806385405df2116101b657806385405df2146107fd57806389b2df311461081d5780638d8f29e2146108bb5780638da5cb5b146108d057600080fd5b8063715018a6146107b357806377036131146107c857806385127a2b146107e857600080fd5b80632e5636e3116102c15780633ccfd60b1161025f5780634f6ccce71161022e5780634f6ccce71461070f57806351e2e1821461072f5780636352211e1461077357806370a082311461079357600080fd5b80633ccfd60b146106a257806342842e0e146106b7578063496122c6146106d75780634b739f8f146106ec57600080fd5b806334f075c01161029b57806334f075c014610621578063359fc7121461064157806335b48afd146106625780633782a2731461068257600080fd5b80632e5636e3146105c15780632f745c59146105e1578063302468251461060157600080fd5b806318160ddd1161032e57806323eafe3f1161030857806323eafe3f1461050257806326baaf781461052257806328e1ddae146105745780632c1cb2dd1461059457600080fd5b806318160ddd146104ad57806319cd8da4146104c257806323b872dd146104e257600080fd5b8063081812fc1161036a578063081812fc1461041f578063095ea7b31461043f5780630f8a46b414610461578063101d961b1461048d57600080fd5b80626d488d1461039057806301ffc9a7146103cd57806306fdde03146103fd575b600080fd5b34801561039c57600080fd5b506015546103b0906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156103d957600080fd5b506103ed6103e83660046148d0565b610bd6565b60405190151581526020016103c4565b34801561040957600080fd5b50610412610c01565b6040516103c4919061594e565b34801561042b57600080fd5b506103b061043a366004614895565b610c93565b34801561044b57600080fd5b5061045f61045a3660046147c6565b610d2d565b005b34801561046d57600080fd5b5061047f6954b40b1f852bda00000081565b6040519081526020016103c4565b34801561049957600080fd5b506018546103b0906001600160a01b031681565b3480156104b957600080fd5b5060085461047f565b3480156104ce57600080fd5b506103ed6104dd366004614895565b610e43565b3480156104ee57600080fd5b5061045f6104fd366004614693565b610ef6565b34801561050e57600080fd5b5061045f61051d36600461490a565b610f27565b34801561052e57600080fd5b5061054261053d366004614620565b611158565b6040805163ffffffff958616815294909316602085015261ffff918216928401929092521660608201526080016103c4565b34801561058057600080fd5b50601e546103b0906001600160a01b031681565b3480156105a057600080fd5b5061047f6105af36600461490a565b60236020526000908152604090205481565b3480156105cd57600080fd5b506103ed6105dc366004614895565b611208565b3480156105ed57600080fd5b5061047f6105fc3660046147c6565b6114d8565b34801561060d57600080fd5b50601d546103b0906001600160a01b031681565b34801561062d57600080fd5b506019546103b0906001600160a01b031681565b34801561064d57600080fd5b50600e546103ed90600160401b900460ff1681565b34801561066e57600080fd5b506017546103b0906001600160a01b031681565b34801561068e57600080fd5b50601c546103b0906001600160a01b031681565b3480156106ae57600080fd5b5061045f61156e565b3480156106c357600080fd5b5061045f6106d2366004614693565b61172b565b3480156106e357600080fd5b5061045f611746565b3480156106f857600080fd5b50600e54600160201b900463ffffffff16156103ed565b34801561071b57600080fd5b5061047f61072a366004614895565b61182c565b34801561073b57600080fd5b5061076061074a366004614895565b60216020526000908152604090205461ffff1681565b60405161ffff90911681526020016103c4565b34801561077f57600080fd5b506103b061078e366004614895565b6118bf565b34801561079f57600080fd5b5061047f6107ae366004614620565b611936565b3480156107bf57600080fd5b5061045f6119bd565b3480156107d457600080fd5b5061045f6107e33660046148ae565b6119f3565b3480156107f457600080fd5b5061047f611a2b565b34801561080957600080fd5b506016546103b0906001600160a01b031681565b34801561082957600080fd5b5061083d61083836600461490a565b611b21565b604080516001600160a01b03909d168d5261ffff9b8c1660208e015260ff909a16998c019990995263ffffffff97881660608c01529890951660808a01529490921660a088015260c0870152151560e086015290151561010085015215156101208401529015156101408301521515610160820152610180016103c4565b3480156108c757600080fd5b5061045f611c45565b3480156108dc57600080fd5b50600b546001600160a01b03166103b0565b3480156108fa57600080fd5b5061045f6109093660046148ae565b611e32565b34801561091a57600080fd5b50610412611eaa565b34801561092f57600080fd5b5061047f61093e366004614895565b60226020526000908152604090205481565b34801561095c57600080fd5b5061047f67016345785d8a000081565b34801561097857600080fd5b5061045f610987366004614798565b611eb9565b34801561099857600080fd5b50600e546109a99063ffffffff1681565b60405163ffffffff90911681526020016103c4565b3480156109ca57600080fd5b506014546103b0906001600160a01b031681565b3480156109ea57600080fd5b5061047f6109f936600461490a565b60246020526000908152604090205481565b348015610a1757600080fd5b506103ed610a2636600461490a565b60256020526000908152604090205460ff1681565b348015610a4757600080fd5b50600e546109a990600160201b900463ffffffff1681565b348015610a6b57600080fd5b5061045f610a7a3660046146d4565b611f7e565b348015610a8b57600080fd5b50610a9460c881565b60405160ff90911681526020016103c4565b348015610ab257600080fd5b50610412610ac1366004614895565b611fb6565b348015610ad257600080fd5b5061047f68056bc75e2d6310000081565b348015610aef57600080fd5b5061045f6120a0565b348015610b0457600080fd5b50600d5461047f9081565b348015610b1b57600080fd5b50610a94601981565b348015610b3057600080fd5b506103ed610b3f36600461465a565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b348015610b7957600080fd5b5061045f610b88366004614620565b612129565b61045f610b9b36600461490a565b6121c1565b348015610bac57600080fd5b50600e546103ed90600160481b900460ff1681565b348015610bcd57600080fd5b50610a94603281565b60006001600160e01b0319821663780e9d6360e01b1480610bfb5750610bfb8261274a565b92915050565b606060008054610c1090615c84565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3c90615c84565b8015610c895780601f10610c5e57610100808354040283529160200191610c89565b820191906000526020600020905b815481529060010190602001808311610c6c57829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610d115760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610d38826118bf565b9050806001600160a01b0316836001600160a01b03161415610da65760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610d08565b336001600160a01b0382161480610dc25750610dc28133610b3f565b610e345760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610d08565b610e3e838361279a565b505050565b60008082118015610e565750611f408211155b610e725760405162461bcd60e51b8152600401610d08906159b3565b60185460405163fbe0fbd560e01b8152600481018490526001600160a01b039091169063fbe0fbd59060240160a06040518083038186803b158015610eb657600080fd5b505afa158015610eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eee91906147f2565b511592915050565b610f003382612808565b610f1c5760405162461bcd60e51b8152600401610d0890615a0c565b610e3e8383836128ff565b6002600c541415610f4a5760405162461bcd60e51b8152600401610d0890615ac1565b6002600c55610f5c61ffff82166118bf565b6001600160a01b0316336001600160a01b031614610fac5760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1037bbb7103a3ab93760991b6044820152606401610d08565b61ffff8116600090815260246020526040902054610fff5760405162461bcd60e51b815260206004820152601060248201526f4e6f2041474c4420746f20636c61696d60801b6044820152606401610d08565b61ffff811660009081526025602052604090205460ff161561105a5760405162461bcd60e51b81526020600482015260146024820152731051d31108185b1c9958591e4818db185a5b595960621b6044820152606401610d08565b60195461ffff8216600090815260246020818152604080842054815163a9059cbb60e01b815233600482015293840152516001600160a01b039094169363a9059cbb936044808501948390030190829087803b1580156110b957600080fd5b505af11580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190614878565b5061ffff81166000818152602560209081526040808320805460ff191660011790556024825291829020548251938452908301527f845acef680dbcf17c98440260e09185de1073b75b3a90880c381d4d3b179f5f1910160405180910390a1506001600c55565b60008080806001600160a01b0385166111bf5760405162461bcd60e51b8152602060048201526024808201527f41747461636b207265636f726420717565727920666f72207a65726f206164646044820152637265737360e01b6064820152608401610d08565b5050506001600160a01b03909116600090815260208052604090205463ffffffff80821693600160201b8304909116925061ffff600160401b8304811692600160501b90041690565b6000808211801561121b5750611f408211155b6112375760405162461bcd60e51b8152600401610d08906159b3565b60185460405163fbe0fbd560e01b8152600481018490526001600160a01b039091169063fbe0fbd59060240160a06040518083038186803b15801561127b57600080fd5b505afa15801561128f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b391906147f2565b516006148061133e5750601854604051630441870d60e41b8152600481018490526001600160a01b039091169063441870d09060240160a06040518083038186803b15801561130157600080fd5b505afa158015611315573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133991906147f2565b516006145b806113c5575060185460405163098779df60e21b8152600481018490526001600160a01b039091169063261de77c9060240160a06040518083038186803b15801561138857600080fd5b505afa15801561139c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c091906147f2565b516006145b8061144c575060185460405163701cc60d60e11b8152600481018490526001600160a01b039091169063e0398c1a9060240160a06040518083038186803b15801561140f57600080fd5b505afa158015611423573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144791906147f2565b516006145b80610bfb5750601854604051630cb7b2cf60e11b8152600481018490526001600160a01b039091169063196f659e9060240160a06040518083038186803b15801561149657600080fd5b505afa1580156114aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ce91906147f2565b5160061492915050565b60006114e383611936565b82106115455760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610d08565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600b546001600160a01b031633146115985760405162461bcd60e51b8152600401610d08906159d7565b600b546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156115d1573d6000803e3d6000fd5b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb611613600b546001600160a01b031690565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561167257600080fd5b505afa158015611686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116aa919061492e565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156116f057600080fd5b505af1158015611704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117289190614878565b50565b610e3e83838360405180602001604052806000815250611f7e565b600e54600160201b900463ffffffff16156117735760405162461bcd60e51b8152600401610d0890615a94565b600e54600160401b900460ff161561179d5760405162461bcd60e51b8152600401610d0890615a5d565b601e546001600160a01b03166000908152602080526040902080546117cc90600160501b900461ffff166118bf565b6001600160a01b0316336001600160a01b0316146118245760405162461bcd60e51b815260206004820152601560248201527426bab9ba10313290323930b3b7b71039b630bcb2b960591b6044820152606401610d08565b611728612aaa565b600061183760085490565b821061189a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610d08565b600882815481106118ad576118ad615d93565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b031680610bfb5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610d08565b60006001600160a01b0382166119a15760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610d08565b506001600160a01b031660009081526003602052604090205490565b600b546001600160a01b031633146119e75760405162461bcd60e51b8152600401610d08906159d7565b6119f16000612ee7565b565b600b546001600160a01b03163314611a1d5760405162461bcd60e51b8152600401610d08906159d7565b611a278282612f39565b5050565b600b546000906001600160a01b03163314611a585760405162461bcd60e51b8152600401610d08906159d7565b600e54600160401b900460ff161515600114611aa35760405162461bcd60e51b815260206004820152600a602482015269139bdd081b1bd8dad95960b21b6044820152606401610d08565b600d5415611aeb5760405162461bcd60e51b8152602060048201526015602482015274416c72656164792073746172746564207475726e7360581b6044820152606401610d08565b6040517f762f260439bb4be3ef6e4dc2786e2e7bd187d3d80b79057d7a424fe98563e33590600090a1611b1c612fb6565b905090565b60008060008060008060008060008060008060008d61ffff1611611b935760405162461bcd60e51b8152602060048201526024808201527f5475726e206e756d6265722068617320746f20626520677265617465722074686044820152630616e20360e41b6064820152608401610d08565b50505061ffff998a166000908152601f60209081526040808320600181015490546024845282852054602590945291909320546001600160a01b039093169d630100000082048e169d60ff8084169e5063ffffffff670100000000000000850481169e506501000000000085049092169c50600160581b84049091169a50929850600160781b820483169750600160801b820483169650600160881b8204831695509282169350600160901b90041690565b6002600c541415611c685760405162461bcd60e51b8152600401610d0890615ac1565b6002600c556000611c7833611936565b905060008111611cca5760405162461bcd60e51b815260206004820152601860248201527f4d757374206f776e206174206c656173742031207475726e00000000000000006044820152606401610d08565b60005b81811015611e29576000611ce133836114d8565b61ffff811660009081526024602052604090205490915015801590611d1a575061ffff811660009081526025602052604090205460ff16155b15611e165760195461ffff8216600090815260246020818152604080842054815163a9059cbb60e01b815233600482015293840152516001600160a01b039094169363a9059cbb936044808501948390030190829087803b158015611d7e57600080fd5b505af1158015611d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db69190614878565b5061ffff81166000818152602560209081526040808320805460ff191660011790556024825291829020548251938452908301527f845acef680dbcf17c98440260e09185de1073b75b3a90880c381d4d3b179f5f1910160405180910390a15b5080611e2181615ce1565b915050611ccd565b50506001600c55565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611a1d5760405162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c006044820152606401610d08565b606060018054610c1090615c84565b6001600160a01b038216331415611f125760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610d08565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611f883383612808565b611fa45760405162461bcd60e51b8152600401610d0890615a0c565b611fb084848484613125565b50505050565b6060611fc06145df565b82611fca81613158565b8252611fd5816131c6565b6020830152611fe38161323f565b6040830152611ff181613336565b606083018190528251602080850151604080870151905160009561201895949091016149d2565b6040516020818303038152906040529050600061207361203b8461ffff166134eb565b612044856135e9565b61204d8561383d565b60405160200161205f9392919061559b565b60405160208183030381529060405261383d565b9050806040516020016120869190615730565b60408051601f198184030181529190529695505050505050565b600b546001600160a01b031633146120ca5760405162461bcd60e51b8152600401610d08906159d7565b600e54600160201b900463ffffffff16156120f75760405162461bcd60e51b8152600401610d0890615a94565b600e54600160401b900460ff16156121215760405162461bcd60e51b8152600401610d0890615a5d565b6119f1612aaa565b600b546001600160a01b031633146121535760405162461bcd60e51b8152600401610d08906159d7565b6001600160a01b0381166121b85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d08565b61172881612ee7565b6002600c5414156121e45760405162461bcd60e51b8152600401610d0890615ac1565b6002600c55600e54600160201b900463ffffffff166122375760405162461bcd60e51b815260206004820152600f60248201526e223930b3b7b71034b99039b630b4b760891b6044820152606401610d08565b600e54600160401b900460ff16156122615760405162461bcd60e51b8152600401610d0890615a5d565b60008161ffff1611801561227b5750611f408161ffff1611155b6122975760405162461bcd60e51b8152600401610d08906159b3565b6017546040516331a9108f60e11b815261ffff831660048201526001600160a01b0390911690636352211e9060240160206040518083038186803b1580156122de57600080fd5b505afa1580156122f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612316919061463d565b6001600160a01b0316336001600160a01b0316146123675760405162461bcd60e51b815260206004820152600e60248201526d2737ba103637b7ba1037bbb732b960911b6044820152606401610d08565b3467016345785d8a000011156123b45760405162461bcd60e51b815260206004820152601260248201527124b739bab33334b1b4b2b73a1022ba3432b960711b6044820152606401610d08565b601954604051636eb1769f60e11b81523360048201523060248201526001600160a01b039091169063dd62ed3e9060440160206040518083038186803b1580156123fd57600080fd5b505afa158015612411573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612435919061492e565b68056bc75e2d63100000111561248d5760405162461bcd60e51b815260206004820152601760248201527f41474c44207370656e64206e6f7420617070726f7665640000000000000000006044820152606401610d08565b6019546040516323b872dd60e01b815233600482015230602482015268056bc75e2d6310000060448201526001600160a01b03909116906323b872dd90606401602060405180830381600087803b1580156124e757600080fd5b505af11580156124fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251f9190614878565b61256b5760405162461bcd60e51b815260206004820152601d60248201527f41474c4420636f756c64206e6f74206265207472616e736665727265640000006044820152606401610d08565b6000612576600d5490565b9050612586600d80546001019055565b6000612591600d5490565b905060006125a28461ffff16611208565b905060006125b38561ffff16610e43565b905060006125c185836139a3565b905060006125d161020086615d1c565b905060006125e1868685856139db565b600e549091506126029060ff831690600160201b900463ffffffff16615c18565b600e805463ffffffff92909216600160201b0267ffffffff00000000199092169190911790556126373389888489888a613af8565b612642878285613e17565b600e546040805161ffff89811682528b16602082015260ff8416818301528715156060820152851515608082015286151560a0820152600160201b90920463ffffffff1660c0830152517ff61039a00c0d89600cf2e68be6b66798bfcebb065f4e59350531259722e6b31d9160e0908290030190a1600e54600160201b900463ffffffff16158015906126d7575061ffff8216155b156126e6576126e4612fb6565b505b600e54600160201b900463ffffffff1661272d576040517ffae7c7cc90f7db3640821bc6ee7c6e4858b63496fda86b80f842dea007e3778390600090a161272b612fb6565b505b61273b338761ffff16613f3b565b50506001600c55505050505050565b60006001600160e01b031982166380ac58cd60e01b148061277b57506001600160e01b03198216635b5e139f60e01b145b80610bfb57506301ffc9a760e01b6001600160e01b0319831614610bfb565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906127cf826118bf565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166128815760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610d08565b600061288c836118bf565b9050806001600160a01b0316846001600160a01b031614806128c75750836001600160a01b03166128bc84610c93565b6001600160a01b0316145b806128f757506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316612912826118bf565b6001600160a01b03161461297a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610d08565b6001600160a01b0382166129dc5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610d08565b6129e7838383613f55565b6129f260008261279a565b6001600160a01b0383166000908152600360205260408120805460019290612a1b908490615c01565b90915550506001600160a01b0382166000908152600360205260408120805460019290612a49908490615b4f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600e54600160481b900460ff1615612afa5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e48191a5cdd1c9a589d5d1959606a1b6044820152606401610d08565b600e54600160201b900463ffffffff1615612b275760405162461bcd60e51b8152600401610d0890615a94565b6019546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015612b6b57600080fd5b505afa158015612b7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba3919061492e565b90506954b40b1f852bda000000811015612bf15760405162461bcd60e51b815260206004820152600f60248201526e139bdd08195b9bdd59da081051d311608a1b6044820152606401610d08565b60008080612bfe600d5490565b601e546001600160a01b03166000908152602080526040812080549293509091612c3d90600160501b900461ffff1669021e19e0c9bab240000061400d565b612c5169021e19e0c9bab240000083615b4f565b601c546001600160a01b031660009081526020805260409020805491935090612c8f90600160501b900461ffff1669021e19e0c9bab240000061400d565b612ca369021e19e0c9bab240000084615b4f565b601d549093506001600160a01b031615612d0957601d546001600160a01b0316600090815260208052604090208054612cf190600160501b900461ffff1669021e19e0c9bab240000061400d565b612d0569021e19e0c9bab240000085615b4f565b9350505b61ffff841660009081526023602052604081205490805b60048160ff161015612e4257600f8160ff1660048110612d4257612d42615d93565b602081049190910154612d6191601f166101000a900460ff1683615b86565b91505b8160ff168961ffff161015612e30578661ffff16612dc28a61ffff168560408051446020808301919091524282840152436060830152608082019390935260a0808201949094528151808203909401845260c0019052815191012090565b612dcc9190615d3d565b612dd7906001615b4f565b9750612dfa8860108360ff1660048110612df357612df3615d93565b015461400d565b60108160ff1660048110612e1057612e10615d93565b0154612e1c9087615b4f565b955088612e2881615cbf565b995050612d64565b80612e3a81615cfc565b915050612d20565b506000612e4f868b615c01565b90508015612e99576000612e64600283615bab565b90506000612e728284615c01565b8754909150612e8c90600160501b900461ffff168361400d565b612e968a8261400d565b50505b600e805469ff0000000000000000001916600160481b1790556040517fb76e5064ebdb0730f80f1dbc7cc9bfd35de8d25c39bc13918f81c5bb6e0f221790600090a150505050505050505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000828152602160209081526040808320546022835281842085905561ffff168084526023835292819020849055600e805460ff60401b19169055805185815291820183905281018390527f0c6471f866af3cc0cc67a48e3441efa20400dffdd1e9110ee03954c1bd37d0119060600160405180910390a1505050565b601b546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b15801561301c57600080fd5b505afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613054919061492e565b10156130945760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420656e6f756768204c494e4b60881b6044820152606401610d08565b600061309f600d5490565b600e805460ff60401b1916600160401b179055601a54601b549192506130c491614039565b600081815260216020908152604091829020805461ffff191661ffff861690811790915582519081529081018390529193507f1d42c205e93d619991c5e1e39354edbaae3a53447001fa90cd06c5ea3c564cf2910160405180910390a15090565b6131308484846128ff565b61313c848484846141c4565b611fb05760405162461bcd60e51b8152600401610d0890615961565b606060008061316684611b21565b50505050505063ffffffff169550505060ff169350505061318a8461ffff166134eb565b613193836134eb565b61319c836134eb565b6040516020016131ae93929190614d6a565b60405160208183030381529060405292505050919050565b606060008060006131d685611b21565b5050505050505061ffff1694509450509350506131f68361ffff166134eb565b6132058263ffffffff166134eb565b6132148463ffffffff166134eb565b60405160200161322693929190615149565b6040516020818303038152906040529350505050919050565b6060600080600061324f85611b21565b5050995099509950505050505050508261328357604051806040016040528060028152602001614e6f60f01b8152506132a0565b6040518060400160405280600381526020016259657360e81b8152505b826132c557604051806040016040528060028152602001614e6f60f01b8152506132e2565b6040518060400160405280600381526020016259657360e81b8152505b8261330757604051806040016040528060028152602001614e6f60f01b815250613324565b6040518060400160405280600381526020016259657360e81b8152505b6040516020016132269392919061542d565b6060600080600061334685611b21565b9b509b5050505098505050505050508461ffff166001146133cb578061339757604051806040016040528060138152602001722a343290323930b3b7b7103634bb32b997171760691b8152506133f2565b60405180604001604052806016815260200175596f7520736c617965642074686520647261676f6e2160501b8152506133f2565b6040518060400160405280600d81526020016c466972737420737472696b652160981b8152505b6000841161340f5760405180602001604052806000815250613465565b600183151514613442576040518060400160405280600b81526020016a020bb30b4b630b136329d160ad1b815250613465565b60405180604001604052806009815260200168021b630b4b6b2b21d160bd1b8152505b60008511613482576040518060200160405280600081525061349c565b61349c613497670de0b6b3a764000087615bab565b6134eb565b600086116134b957604051806020016040528060008152506134d8565b60405180604001604052806005815260200164081051d31160da1b8152505b6040516020016132269493929190614a29565b60608161350f5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613539578061352381615ce1565b91506135329050600a83615bab565b9150613513565b60008167ffffffffffffffff81111561355457613554615da9565b6040519080825280601f01601f19166020018201604052801561357e576020820181803683370190505b5090505b84156128f757613593600183615c01565b91506135a0600a86615d3d565b6135ab906030615b4f565b60f81b8183815181106135c0576135c0615d93565b60200101906001600160f81b031916908160001a9053506135e2600a86615bab565b9450613582565b606060008060008060008060008060008060006136058d611b21565b9b509b509b509b509b509b509b509b509b509b509b5050613624614606565b6136318c61ffff166134eb565b61363d8c60ff166134eb565b61364c8c63ffffffff166134eb565b6136598c61ffff166134eb565b60405160200161366c9493929190615775565b60408051808303601f19018152919052815261368d63ffffffff89166134eb565b6136a2613497670de0b6b3a76400008a615bab565b876136b6576136b160006134eb565b6136c0565b6136c060196134eb565b876136d4576136cf60006134eb565b6136de565b6136de60326134eb565b6040516020016136f1949392919061527b565b60408051808303601f1901815291905260208201528361372d57604051806040016040528060048152602001631127379160e11b81525061374c565b60405180604001604052806005815260200164112cb2b99160d91b8152505b8361377357604051806040016040528060048152602001631127379160e11b815250613792565b60405180604001604052806005815260200164112cb2b99160d91b8152505b836137b957604051806040016040528060048152602001631127379160e11b8152506137d8565b60405180604001604052806005815260200164112cb2b99160d91b8152505b6040516020016137ea9392919061503d565b60408051808303601f190181529181528281018290528251602080850151925160009461381a949290910161498f565b60408051601f198184030181529190529f9e505050505050505050505050505050565b80516060908061385d575050604080516020810190915260008152919050565b6000600361386c836002615b4f565b6138769190615bab565b613881906004615bbf565b90506000613890826020615b4f565b67ffffffffffffffff8111156138a8576138a8615da9565b6040519080825280601f01601f1916602001820160405280156138d2576020820181803683370190505b5090506000604051806060016040528060408152602001615df9604091399050600181016020830160005b8681101561395e576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b8352600490920191016138fd565b506003860660018114613978576002811461398957613995565b613d3d60f01b600119830152613995565b603d60f81b6000198301525b505050918152949350505050565b60008061ffff8416158015906139b7575082155b156139d4576139c584611b21565b50909a50505050505050505050505b9392505050565b6000806001841515146139ef5760006139f2565b60325b600186151514613a03576000613a06565b60195b613a109190615b86565b90506000613a1f601983615b86565b90506000613a2e8260c8615c35565b90506000613a3c868a615bde565b61ffff8082166000908152602360205260408120549293509060ff8087169190861690613aa7908e168560408051446020808301919091524282840152436060830152608082019390935260a0808201949094528151808203909401845260c0019052815191012090565b613ab19190615d3d565b613abb9190615b4f565b600e54909150600160201b900463ffffffff1660ff82161115613aea5750600e54600160201b900463ffffffff165b9a9950505050505050505050565b61ffff85166000908152601f602090815260408083206001600160a01b03808c1685529280529220601c54909116613b4657601c80546001600160a01b0319166001600160a01b038b161790555b601c546001600160a01b0316600090815260208052604081208254909160ff891691849190613b7c90849063ffffffff16615b67565b825463ffffffff9182166101009390930a928302919092021990911617905550815461ffff808a16600160501b0261ffff60501b19909216919091178084556001918491600891613bd7918591600160401b90910416615b29565b825461ffff9182166101009390930a9283029190920219909116179055508054825463ffffffff91821691161115613c2557601c80546001600160a01b0319166001600160a01b038c161790555b878360000160016101000a81548161ffff021916908361ffff160217905550898360010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550888360000160036101000a81548161ffff021916908361ffff160217905550868360000160006101000a81548160ff021916908360ff1602179055508160000160009054906101000a900463ffffffff168360000160076101000a81548163ffffffff021916908363ffffffff1602179055508160000160089054906101000a900461ffff168360000160056101000a81548161ffff021916908361ffff160217905550600e60049054906101000a900463ffffffff1683600001600b6101000a81548163ffffffff021916908363ffffffff1602179055508583600001600f6101000a81548160ff021916908315150217905550848360000160106101000a81548160ff021916908315150217905550838360000160116101000a81548160ff021916908315150217905550600e60049054906101000a900463ffffffff1663ffffffff166000148360000160126101000a81548160ff0219169083151502179055508260000160129054906101000a900460ff161515600115151415613e0b57601e80546001600160a01b0319166001600160a01b038c161790555b50505050505050505050565b61ffff83166000908152601f6020908152604080832060018101546001600160a01b0390811685529280529220601d54909116613e73576001820154601d80546001600160a01b0319166001600160a01b039092169190911790555b601d546001600160a01b0316600090815260208052604090208315156001148015613eab57508254600160881b900460ff1615156001145b15613f3357815460ff8616908390600490613ed4908490600160201b900463ffffffff16615b67565b82546101009290920a63ffffffff81810219909316918316021790915582548454600160201b91829004831691900490911611159050613f33576001830154601d80546001600160a01b0319166001600160a01b039092169190911790555b505050505050565b611a278282604051806020016040528060008152506142ce565b6001600160a01b038316613fb057613fab81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b613fd3565b816001600160a01b0316836001600160a01b031614613fd357613fd38382614301565b6001600160a01b038216613fea57610e3e8161439e565b826001600160a01b0316826001600160a01b031614610e3e57610e3e828261444d565b61ffff821660009081526024602052604081208054839290614030908490615b4f565b90915550505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634000aea07f0000000000000000000000000000000000000000000000000000000000000000848660006040516020016140a9929190918252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016140d693929190615927565b602060405180830381600087803b1580156140f057600080fd5b505af1158015614104573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141289190614878565b506000838152600a6020818152604080842054815180840189905280830186905230606082015260808082018390528351808303909101815260a090910190925281519183019190912093879052919052614184906001615b4f565b6000858152600a60205260409020556128f78482604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60006001600160a01b0384163b156142c657604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906142089033908990889088906004016158f4565b602060405180830381600087803b15801561422257600080fd5b505af1925050508015614252575060408051601f3d908101601f1916820190925261424f918101906148ed565b60015b6142ac573d808015614280576040519150601f19603f3d011682016040523d82523d6000602084013e614285565b606091505b5080516142a45760405162461bcd60e51b8152600401610d0890615961565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506128f7565b5060016128f7565b6142d88383614491565b6142e560008484846141c4565b610e3e5760405162461bcd60e51b8152600401610d0890615961565b6000600161430e84611936565b6143189190615c01565b60008381526007602052604090205490915080821461436b576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906143b090600190615c01565b600083815260096020526040812054600880549394509092849081106143d8576143d8615d93565b9060005260206000200154905080600883815481106143f9576143f9615d93565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061443157614431615d7d565b6001900381819060005260206000200160009055905550505050565b600061445883611936565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b0382166144e75760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610d08565b6000818152600260205260409020546001600160a01b03161561454c5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610d08565b61455860008383613f55565b6001600160a01b0382166000908152600360205260408120805460019290614581908490615b4f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60405180608001604052806004905b60608152602001906001900390816145ee5790505090565b6040805160608082019092529081526002602082016145ee565b60006020828403121561463257600080fd5b81356139d481615dbf565b60006020828403121561464f57600080fd5b81516139d481615dbf565b6000806040838503121561466d57600080fd5b823561467881615dbf565b9150602083013561468881615dbf565b809150509250929050565b6000806000606084860312156146a857600080fd5b83356146b381615dbf565b925060208401356146c381615dbf565b929592945050506040919091013590565b600080600080608085870312156146ea57600080fd5b84356146f581615dbf565b935060208581013561470681615dbf565b935060408601359250606086013567ffffffffffffffff8082111561472a57600080fd5b818801915088601f83011261473e57600080fd5b81358181111561475057614750615da9565b614762601f8201601f19168501615af8565b9150808252898482850101111561477857600080fd5b808484018584013760008482840101525080935050505092959194509250565b600080604083850312156147ab57600080fd5b82356147b681615dbf565b9150602083013561468881615dd4565b600080604083850312156147d957600080fd5b82356147e481615dbf565b946020939093013593505050565b600060a0828403121561480457600080fd5b82601f83011261481357600080fd5b60405160a0810181811067ffffffffffffffff8211171561483657614836615da9565b604052808360a0810186101561484b57600080fd5b60005b600581101561486d57815183526020928301929091019060010161484e565b509195945050505050565b60006020828403121561488a57600080fd5b81516139d481615dd4565b6000602082840312156148a757600080fd5b5035919050565b600080604083850312156148c157600080fd5b50508035926020909101359150565b6000602082840312156148e257600080fd5b81356139d481615de2565b6000602082840312156148ff57600080fd5b81516139d481615de2565b60006020828403121561491c57600080fd5b813561ffff811681146139d457600080fd5b60006020828403121561494057600080fd5b5051919050565b6000815180845261495f816020860160208601615c58565b601f01601f19169290920160200192915050565b60008151614985818560208601615c58565b9290920192915050565b600084516149a1818460208901615c58565b8451908301906149b5818360208901615c58565b84519101906149c8818360208801615c58565b0195945050505050565b600085516149e4818460208a01615c58565b8551908301906149f8818360208a01615c58565b8551910190614a0b818360208901615c58565b8451910190614a1e818360208801615c58565b019695505050505050565b60008551614a3b818460208a01615c58565b80830190507f3c2f746578743e3c7465787420783d2233302220793d223331352220636c6173815268399e913130b9b2911f60b91b60208201528551614a88816029840160208a01615c58565b8551910190614a9e816029840160208901615c58565b8451910190614ab4816029840160208801615c58565b7f3c2f746578743e3c7265637420783d223332322e322220793d223332352e3222602992909101918201527f207472616e73666f726d3d226d617472697828302e37333432202d302e36373860498201527f3920302e3637383920302e37333432202d3133362e33383136203330372e393760698201527f383129222066696c6c3d2223463242313338222077696474683d22352e39222060898201527f6865696768743d22352e39222f3e3c7265637420783d223332362e362220793d60a98201527f223332312e3222207472616e73666f726d3d226d617472697828302e3733343260c98201527f202d302e3637383920302e3637383920302e37333432202d3133322e3530373560e98201527f203330392e3835363329222066696c6c3d2223423738333330222077696474686101098201527f3d22352e3922206865696768743d22352e39222f3e3c7265637420783d2233326101298201527f362e322220793d223332392e3622207472616e73666f726d3d226d61747269786101498201527f28302e37333432202d302e3637383920302e3637383920302e37333432202d316101698201527f33382e32353938203331312e3835323129222066696c6c3d22234237383333306101898201527f222077696474683d22352e3922206865696768743d22352e39222f3e3c7265636101a98201527f7420783d223333302e362220793d223332352e3622207472616e73666f726d3d6101c98201527f226d617472697828302e37333432202d302e3637383920302e3637383920302e6101e98201527f37333432202d3133342e33383537203331332e3733303429222066696c6c3d226102098201527f23463242313338222077696474683d22352e3922206865696768743d22352e396102298201526811179f1e17b9bb339f60b91b610249820152610252019695505050505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f73766722207072657365727665417370656374526174696f3d22784d6960208201527f6e594d696e206d656574222076696577426f783d22302030203335302033353060408201527f223e3c7374796c653e2e62617365207b2066696c6c3a20234646464346433b2060608201527f666f6e742d66616d696c793a206d6f6e6f73706163653b20666f6e742d73697a60808201527f653a20313470783b207d202e7469746c65207b2066696c6c3a2023464646434660a08201527f433b20666f6e742d66616d696c793a206d6f6e6f73706163653b20666f6e742d60c08201527f73697a653a20323470783b20746578742d616e63686f723a206d6964646c653b60e08201527f20646f6d696e616e742d626173656c696e653a206d6964646c653b207d3c2f736101008201527f74796c653e3c726563742077696474683d223130302522206865696768743d226101208201527f31303025222066696c6c3d222330303346363322202f3e3c7465787420783d226101408201527f3137352220793d2233352220636c6173733d227469746c65223e5155455354536101608201527f20464f52204c4f4f543c2f746578743e3c7465787420783d2233302220793d226101808201527501c1a911031b630b9b99e913130b9b2911f2a3ab937160551b6101a0820152600061503461502e614fdf614fd9614f966101b687018a614973565b7f3c2f746578743e3c7465787420783d2233302220793d223131352220636c61738152700399e913130b9b2911f2230b6b0b3b29d1607d1b602082015260310190565b87614973565b7f2048503c2f746578743e3c7465787420783d2233302220793d2231333522206381527f6c6173733d2262617365223e52656d61696e696e673a20000000000000000000602082015260370190565b84614973565b95945050505050565b7f7d2c7b2274726169745f74797065223a202250726f766964656420537570706f81526d0393a111610113b30b63ab2911d160951b60208201526000845161508c81602e850160208901615c58565b7f7d2c7b2274726169745f74797065223a202241474c4420436c61696d6564222c602e9184019182015269010113b30b63ab2911d160b51b604e82015284516150dc816058840160208901615c58565b7f7d2c7b2274726169745f74797065223a2022447261676f6e20536c6179657222605892909101918201526a01610113b30b63ab2911d160ad1b6078820152835161512e816083840160208801615c58565b607d60f81b6083929091019182015260840195945050505050565b7f2048503c2f746578743e3c7465787420783d2233302220793d2231353522206381527f6c6173733d2262617365223e4c6f6f74204261673a20230000000000000000006020820152600084516151a7816037850160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223137352220636c61736037918401918201527f733d2262617365223e5475726e7320506c617965643a200000000000000000006057820152845161520a81606e840160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223139352220636c6173606e92909101918201527f733d2262617365223e546f74616c2044616d6167653a20000000000000000000608e820152835161526e8160a5840160208801615c58565b0160a50195945050505050565b7f7d2c7b2274726169745f74797065223a2022447261676f6e204850222c202276815266030b63ab2911d160cd1b6020820152600085516152c3816027850160208a01615c58565b7f7d2c7b2274726169745f74797065223a202241474c4420417661696c61626c656027918401918201527f222c2022646973706c61795f74797065223a20226e756d626572222c202276616047820152650363ab2911d160d51b6067820152855161533581606d840160208a01615c58565b7f7d2c7b2274726169745f74797065223a202244616d61676520426f6f7374222c606d92909101918201527f2022646973706c61795f74797065223a2022626f6f73745f6e756d626572222c608d82015269010113b30b63ab2911d160b51b60ad82015284516153ac8160b7840160208901615c58565b61542161541b60b7838501017f7d2c7b2274726169745f74797065223a2022537570706f727420426f6f73742281527f2c2022646973706c61795f74797065223a2022626f6f73745f6e756d6265722260208201526a01610113b30b63ab2911d160ad1b6040820152604b0190565b86614973565b98975050505050505050565b7f3c2f746578743e3c7465787420783d2233302220793d223232352220636c617381527f733d2262617365223e44616d61676520426f6f73743a2000000000000000000060208201526000845161548b816037850160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223234352220636c61736037918401918201527f733d2262617365223e537570706f727420426f6f73743a200000000000000000605782015284516154ee81606f840160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223236352220636c6173606f92909101918201527f733d2262617365223e50726f766964656420537570706f72743a200000000000608f82015283516155528160aa840160208801615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223239352220636c617360aa929091019182015268399e913130b9b2911f60b91b60ca82015260d30195945050505050565b6e03d913730b6b2911d10112a3ab9371608d1b815283516000906155c681600f850160208901615c58565b71222c202261747472696275746573223a205b60701b600f9184019182015284516155f8816021840160208901615c58565b7f5d2c20226465736372697074696f6e223a202251756573747320666f72204c6f602192909101918201527f6f742061726520626174746c65207265636f7264732073746f726564206f6e2d60418201527f636861696e20666f722061204d554420746f20736c6179206120647261676f6e60618201527f20746861742773207261766167696e6720612076696c6c6167652e20506c617960818201527f657273206d75737420776f726b20746f67657468657220746f2064656665617460a18201527f20697420616e64207265617020746865207265776172647321222c2022696d6160c18201527f6765223a2022646174613a696d6167652f7376672b786d6c3b6261736536342c60e1820152615726615718610101830186614973565b61227d60f01b815260020190565b9695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161576881601d850160208701615c58565b91909101601d0192915050565b7f7b2274726169745f74797065223a20224c6f6f74222c202276616c7565223a208152601160f91b6020820152600085516157b7816021850160208a01615c58565b7f227d2c7b2274726169745f74797065223a202244616d616765204465616c74226021918401918201526a01610113b30b63ab2911d160ad1b6041820152855161580881604c840160208a01615c58565b7f7d2c7b2274726169745f74797065223a202243756d756c61746976652044616d604c92909101918201527f616765204465616c74222c2022646973706c61795f74797065223a20226e756d606c8201526e03132b9111610113b30b63ab2911d1608d1b608c8201819052855161588681609b850160208a01615c58565b7f7d2c7b2274726169745f74797065223a202243756d756c617469766520547572609b93909101928301527f6e7320506c61796564222c2022646973706c61795f74797065223a20226e756d60bb83015260db8201526158e960ea820185614973565b979650505050505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061572690830184614947565b60018060a01b03841681528260208201526060604082015260006150346060830184614947565b6020815260006139d46020830184614947565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252600a9082015269125b9d985b1a5908125160b21b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526019908201527f57616974696e6720666f722056524620746f2072657475726e00000000000000604082015260600190565b602080825260139082015272223930b3b7b71034b9903737ba1039b630b4b760691b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715615b2157615b21615da9565b604052919050565b600061ffff808316818516808303821115615b4657615b46615d51565b01949350505050565b60008219821115615b6257615b62615d51565b500190565b600063ffffffff808316818516808303821115615b4657615b46615d51565b600060ff821660ff84168060ff03821115615ba357615ba3615d51565b019392505050565b600082615bba57615bba615d67565b500490565b6000816000190483118215151615615bd957615bd9615d51565b500290565b600061ffff83811690831681811015615bf957615bf9615d51565b039392505050565b600082821015615c1357615c13615d51565b500390565b600063ffffffff83811690831681811015615bf957615bf9615d51565b600060ff821660ff841680821015615c4f57615c4f615d51565b90039392505050565b60005b83811015615c73578181015183820152602001615c5b565b83811115611fb05750506000910152565b600181811c90821680615c9857607f821691505b60208210811415615cb957634e487b7160e01b600052602260045260246000fd5b50919050565b600061ffff80831681811415615cd757615cd7615d51565b6001019392505050565b6000600019821415615cf557615cf5615d51565b5060010190565b600060ff821660ff811415615d1357615d13615d51565b60010192915050565b600061ffff80841680615d3157615d31615d67565b92169190910692915050565b600082615d4c57615d4c615d67565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461172857600080fd5b801515811461172857600080fd5b6001600160e01b03198116811461172857600080fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220ef0216e22d8311343546cf1c3889cde1f71c1dd61c26a64afb6fd00c2f21964764736f6c63430008070033000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952000000000000000000000000514910771af9ca656af840dff83e8264ecf986caaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af4450000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000ff9c1b15b16263c61d017ee9f65c50e4ae0113d70000000000000000000000003eb43b1545a360d1d065cb7539339363dfd445f300000000000000000000000032353a6c91143bfd6c7d363b546e62a9a2489a20
Deployed Bytecode
0x60806040526004361061038b5760003560e01c8063715018a6116101dc578063b128505b11610102578063deb61286116100a0578063f6a9e2011161006f578063f6a9e20114610b8d578063f6eac58f14610b0f578063f84b903e14610ba0578063fe89483614610bc157600080fd5b8063deb6128614610af8578063e53fb91014610b0f578063e985e9c514610b24578063f2fde38b14610b6d57600080fd5b8063c5ab60c2116100dc578063c5ab60c214610a7f578063c87b56dd14610aa6578063cde9729e14610ac6578063d095497814610ae357600080fd5b8063b128505b14610a0b578063b43be74514610a3b578063b88d4fde14610a5f57600080fd5b806394985ddd1161017a578063a22cb46511610149578063a22cb4651461096c578063a2c6188b1461098c578063a8af32e9146109be578063aa749dbf146109de57600080fd5b806394985ddd146108ee57806395d89b411461090e5780639bef920014610923578063a035b1fe1461095057600080fd5b806385405df2116101b657806385405df2146107fd57806389b2df311461081d5780638d8f29e2146108bb5780638da5cb5b146108d057600080fd5b8063715018a6146107b357806377036131146107c857806385127a2b146107e857600080fd5b80632e5636e3116102c15780633ccfd60b1161025f5780634f6ccce71161022e5780634f6ccce71461070f57806351e2e1821461072f5780636352211e1461077357806370a082311461079357600080fd5b80633ccfd60b146106a257806342842e0e146106b7578063496122c6146106d75780634b739f8f146106ec57600080fd5b806334f075c01161029b57806334f075c014610621578063359fc7121461064157806335b48afd146106625780633782a2731461068257600080fd5b80632e5636e3146105c15780632f745c59146105e1578063302468251461060157600080fd5b806318160ddd1161032e57806323eafe3f1161030857806323eafe3f1461050257806326baaf781461052257806328e1ddae146105745780632c1cb2dd1461059457600080fd5b806318160ddd146104ad57806319cd8da4146104c257806323b872dd146104e257600080fd5b8063081812fc1161036a578063081812fc1461041f578063095ea7b31461043f5780630f8a46b414610461578063101d961b1461048d57600080fd5b80626d488d1461039057806301ffc9a7146103cd57806306fdde03146103fd575b600080fd5b34801561039c57600080fd5b506015546103b0906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156103d957600080fd5b506103ed6103e83660046148d0565b610bd6565b60405190151581526020016103c4565b34801561040957600080fd5b50610412610c01565b6040516103c4919061594e565b34801561042b57600080fd5b506103b061043a366004614895565b610c93565b34801561044b57600080fd5b5061045f61045a3660046147c6565b610d2d565b005b34801561046d57600080fd5b5061047f6954b40b1f852bda00000081565b6040519081526020016103c4565b34801561049957600080fd5b506018546103b0906001600160a01b031681565b3480156104b957600080fd5b5060085461047f565b3480156104ce57600080fd5b506103ed6104dd366004614895565b610e43565b3480156104ee57600080fd5b5061045f6104fd366004614693565b610ef6565b34801561050e57600080fd5b5061045f61051d36600461490a565b610f27565b34801561052e57600080fd5b5061054261053d366004614620565b611158565b6040805163ffffffff958616815294909316602085015261ffff918216928401929092521660608201526080016103c4565b34801561058057600080fd5b50601e546103b0906001600160a01b031681565b3480156105a057600080fd5b5061047f6105af36600461490a565b60236020526000908152604090205481565b3480156105cd57600080fd5b506103ed6105dc366004614895565b611208565b3480156105ed57600080fd5b5061047f6105fc3660046147c6565b6114d8565b34801561060d57600080fd5b50601d546103b0906001600160a01b031681565b34801561062d57600080fd5b506019546103b0906001600160a01b031681565b34801561064d57600080fd5b50600e546103ed90600160401b900460ff1681565b34801561066e57600080fd5b506017546103b0906001600160a01b031681565b34801561068e57600080fd5b50601c546103b0906001600160a01b031681565b3480156106ae57600080fd5b5061045f61156e565b3480156106c357600080fd5b5061045f6106d2366004614693565b61172b565b3480156106e357600080fd5b5061045f611746565b3480156106f857600080fd5b50600e54600160201b900463ffffffff16156103ed565b34801561071b57600080fd5b5061047f61072a366004614895565b61182c565b34801561073b57600080fd5b5061076061074a366004614895565b60216020526000908152604090205461ffff1681565b60405161ffff90911681526020016103c4565b34801561077f57600080fd5b506103b061078e366004614895565b6118bf565b34801561079f57600080fd5b5061047f6107ae366004614620565b611936565b3480156107bf57600080fd5b5061045f6119bd565b3480156107d457600080fd5b5061045f6107e33660046148ae565b6119f3565b3480156107f457600080fd5b5061047f611a2b565b34801561080957600080fd5b506016546103b0906001600160a01b031681565b34801561082957600080fd5b5061083d61083836600461490a565b611b21565b604080516001600160a01b03909d168d5261ffff9b8c1660208e015260ff909a16998c019990995263ffffffff97881660608c01529890951660808a01529490921660a088015260c0870152151560e086015290151561010085015215156101208401529015156101408301521515610160820152610180016103c4565b3480156108c757600080fd5b5061045f611c45565b3480156108dc57600080fd5b50600b546001600160a01b03166103b0565b3480156108fa57600080fd5b5061045f6109093660046148ae565b611e32565b34801561091a57600080fd5b50610412611eaa565b34801561092f57600080fd5b5061047f61093e366004614895565b60226020526000908152604090205481565b34801561095c57600080fd5b5061047f67016345785d8a000081565b34801561097857600080fd5b5061045f610987366004614798565b611eb9565b34801561099857600080fd5b50600e546109a99063ffffffff1681565b60405163ffffffff90911681526020016103c4565b3480156109ca57600080fd5b506014546103b0906001600160a01b031681565b3480156109ea57600080fd5b5061047f6109f936600461490a565b60246020526000908152604090205481565b348015610a1757600080fd5b506103ed610a2636600461490a565b60256020526000908152604090205460ff1681565b348015610a4757600080fd5b50600e546109a990600160201b900463ffffffff1681565b348015610a6b57600080fd5b5061045f610a7a3660046146d4565b611f7e565b348015610a8b57600080fd5b50610a9460c881565b60405160ff90911681526020016103c4565b348015610ab257600080fd5b50610412610ac1366004614895565b611fb6565b348015610ad257600080fd5b5061047f68056bc75e2d6310000081565b348015610aef57600080fd5b5061045f6120a0565b348015610b0457600080fd5b50600d5461047f9081565b348015610b1b57600080fd5b50610a94601981565b348015610b3057600080fd5b506103ed610b3f36600461465a565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b348015610b7957600080fd5b5061045f610b88366004614620565b612129565b61045f610b9b36600461490a565b6121c1565b348015610bac57600080fd5b50600e546103ed90600160481b900460ff1681565b348015610bcd57600080fd5b50610a94603281565b60006001600160e01b0319821663780e9d6360e01b1480610bfb5750610bfb8261274a565b92915050565b606060008054610c1090615c84565b80601f0160208091040260200160405190810160405280929190818152602001828054610c3c90615c84565b8015610c895780601f10610c5e57610100808354040283529160200191610c89565b820191906000526020600020905b815481529060010190602001808311610c6c57829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610d115760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610d38826118bf565b9050806001600160a01b0316836001600160a01b03161415610da65760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610d08565b336001600160a01b0382161480610dc25750610dc28133610b3f565b610e345760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610d08565b610e3e838361279a565b505050565b60008082118015610e565750611f408211155b610e725760405162461bcd60e51b8152600401610d08906159b3565b60185460405163fbe0fbd560e01b8152600481018490526001600160a01b039091169063fbe0fbd59060240160a06040518083038186803b158015610eb657600080fd5b505afa158015610eca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eee91906147f2565b511592915050565b610f003382612808565b610f1c5760405162461bcd60e51b8152600401610d0890615a0c565b610e3e8383836128ff565b6002600c541415610f4a5760405162461bcd60e51b8152600401610d0890615ac1565b6002600c55610f5c61ffff82166118bf565b6001600160a01b0316336001600160a01b031614610fac5760405162461bcd60e51b815260206004820152600d60248201526c26bab9ba1037bbb7103a3ab93760991b6044820152606401610d08565b61ffff8116600090815260246020526040902054610fff5760405162461bcd60e51b815260206004820152601060248201526f4e6f2041474c4420746f20636c61696d60801b6044820152606401610d08565b61ffff811660009081526025602052604090205460ff161561105a5760405162461bcd60e51b81526020600482015260146024820152731051d31108185b1c9958591e4818db185a5b595960621b6044820152606401610d08565b60195461ffff8216600090815260246020818152604080842054815163a9059cbb60e01b815233600482015293840152516001600160a01b039094169363a9059cbb936044808501948390030190829087803b1580156110b957600080fd5b505af11580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190614878565b5061ffff81166000818152602560209081526040808320805460ff191660011790556024825291829020548251938452908301527f845acef680dbcf17c98440260e09185de1073b75b3a90880c381d4d3b179f5f1910160405180910390a1506001600c55565b60008080806001600160a01b0385166111bf5760405162461bcd60e51b8152602060048201526024808201527f41747461636b207265636f726420717565727920666f72207a65726f206164646044820152637265737360e01b6064820152608401610d08565b5050506001600160a01b03909116600090815260208052604090205463ffffffff80821693600160201b8304909116925061ffff600160401b8304811692600160501b90041690565b6000808211801561121b5750611f408211155b6112375760405162461bcd60e51b8152600401610d08906159b3565b60185460405163fbe0fbd560e01b8152600481018490526001600160a01b039091169063fbe0fbd59060240160a06040518083038186803b15801561127b57600080fd5b505afa15801561128f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b391906147f2565b516006148061133e5750601854604051630441870d60e41b8152600481018490526001600160a01b039091169063441870d09060240160a06040518083038186803b15801561130157600080fd5b505afa158015611315573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133991906147f2565b516006145b806113c5575060185460405163098779df60e21b8152600481018490526001600160a01b039091169063261de77c9060240160a06040518083038186803b15801561138857600080fd5b505afa15801561139c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c091906147f2565b516006145b8061144c575060185460405163701cc60d60e11b8152600481018490526001600160a01b039091169063e0398c1a9060240160a06040518083038186803b15801561140f57600080fd5b505afa158015611423573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144791906147f2565b516006145b80610bfb5750601854604051630cb7b2cf60e11b8152600481018490526001600160a01b039091169063196f659e9060240160a06040518083038186803b15801561149657600080fd5b505afa1580156114aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ce91906147f2565b5160061492915050565b60006114e383611936565b82106115455760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610d08565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b600b546001600160a01b031633146115985760405162461bcd60e51b8152600401610d08906159d7565b600b546040516001600160a01b03909116904780156108fc02916000818181858888f193505050501580156115d1573d6000803e3d6000fd5b507f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b031663a9059cbb611613600b546001600160a01b031690565b6040516370a0823160e01b81523060048201527f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316906370a082319060240160206040518083038186803b15801561167257600080fd5b505afa158015611686573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116aa919061492e565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156116f057600080fd5b505af1158015611704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117289190614878565b50565b610e3e83838360405180602001604052806000815250611f7e565b600e54600160201b900463ffffffff16156117735760405162461bcd60e51b8152600401610d0890615a94565b600e54600160401b900460ff161561179d5760405162461bcd60e51b8152600401610d0890615a5d565b601e546001600160a01b03166000908152602080526040902080546117cc90600160501b900461ffff166118bf565b6001600160a01b0316336001600160a01b0316146118245760405162461bcd60e51b815260206004820152601560248201527426bab9ba10313290323930b3b7b71039b630bcb2b960591b6044820152606401610d08565b611728612aaa565b600061183760085490565b821061189a5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610d08565b600882815481106118ad576118ad615d93565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b031680610bfb5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610d08565b60006001600160a01b0382166119a15760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610d08565b506001600160a01b031660009081526003602052604090205490565b600b546001600160a01b031633146119e75760405162461bcd60e51b8152600401610d08906159d7565b6119f16000612ee7565b565b600b546001600160a01b03163314611a1d5760405162461bcd60e51b8152600401610d08906159d7565b611a278282612f39565b5050565b600b546000906001600160a01b03163314611a585760405162461bcd60e51b8152600401610d08906159d7565b600e54600160401b900460ff161515600114611aa35760405162461bcd60e51b815260206004820152600a602482015269139bdd081b1bd8dad95960b21b6044820152606401610d08565b600d5415611aeb5760405162461bcd60e51b8152602060048201526015602482015274416c72656164792073746172746564207475726e7360581b6044820152606401610d08565b6040517f762f260439bb4be3ef6e4dc2786e2e7bd187d3d80b79057d7a424fe98563e33590600090a1611b1c612fb6565b905090565b60008060008060008060008060008060008060008d61ffff1611611b935760405162461bcd60e51b8152602060048201526024808201527f5475726e206e756d6265722068617320746f20626520677265617465722074686044820152630616e20360e41b6064820152608401610d08565b50505061ffff998a166000908152601f60209081526040808320600181015490546024845282852054602590945291909320546001600160a01b039093169d630100000082048e169d60ff8084169e5063ffffffff670100000000000000850481169e506501000000000085049092169c50600160581b84049091169a50929850600160781b820483169750600160801b820483169650600160881b8204831695509282169350600160901b90041690565b6002600c541415611c685760405162461bcd60e51b8152600401610d0890615ac1565b6002600c556000611c7833611936565b905060008111611cca5760405162461bcd60e51b815260206004820152601860248201527f4d757374206f776e206174206c656173742031207475726e00000000000000006044820152606401610d08565b60005b81811015611e29576000611ce133836114d8565b61ffff811660009081526024602052604090205490915015801590611d1a575061ffff811660009081526025602052604090205460ff16155b15611e165760195461ffff8216600090815260246020818152604080842054815163a9059cbb60e01b815233600482015293840152516001600160a01b039094169363a9059cbb936044808501948390030190829087803b158015611d7e57600080fd5b505af1158015611d92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db69190614878565b5061ffff81166000818152602560209081526040808320805460ff191660011790556024825291829020548251938452908301527f845acef680dbcf17c98440260e09185de1073b75b3a90880c381d4d3b179f5f1910160405180910390a15b5080611e2181615ce1565b915050611ccd565b50506001600c55565b336001600160a01b037f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb79521614611a1d5760405162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c006044820152606401610d08565b606060018054610c1090615c84565b6001600160a01b038216331415611f125760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610d08565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611f883383612808565b611fa45760405162461bcd60e51b8152600401610d0890615a0c565b611fb084848484613125565b50505050565b6060611fc06145df565b82611fca81613158565b8252611fd5816131c6565b6020830152611fe38161323f565b6040830152611ff181613336565b606083018190528251602080850151604080870151905160009561201895949091016149d2565b6040516020818303038152906040529050600061207361203b8461ffff166134eb565b612044856135e9565b61204d8561383d565b60405160200161205f9392919061559b565b60405160208183030381529060405261383d565b9050806040516020016120869190615730565b60408051601f198184030181529190529695505050505050565b600b546001600160a01b031633146120ca5760405162461bcd60e51b8152600401610d08906159d7565b600e54600160201b900463ffffffff16156120f75760405162461bcd60e51b8152600401610d0890615a94565b600e54600160401b900460ff16156121215760405162461bcd60e51b8152600401610d0890615a5d565b6119f1612aaa565b600b546001600160a01b031633146121535760405162461bcd60e51b8152600401610d08906159d7565b6001600160a01b0381166121b85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610d08565b61172881612ee7565b6002600c5414156121e45760405162461bcd60e51b8152600401610d0890615ac1565b6002600c55600e54600160201b900463ffffffff166122375760405162461bcd60e51b815260206004820152600f60248201526e223930b3b7b71034b99039b630b4b760891b6044820152606401610d08565b600e54600160401b900460ff16156122615760405162461bcd60e51b8152600401610d0890615a5d565b60008161ffff1611801561227b5750611f408161ffff1611155b6122975760405162461bcd60e51b8152600401610d08906159b3565b6017546040516331a9108f60e11b815261ffff831660048201526001600160a01b0390911690636352211e9060240160206040518083038186803b1580156122de57600080fd5b505afa1580156122f2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612316919061463d565b6001600160a01b0316336001600160a01b0316146123675760405162461bcd60e51b815260206004820152600e60248201526d2737ba103637b7ba1037bbb732b960911b6044820152606401610d08565b3467016345785d8a000011156123b45760405162461bcd60e51b815260206004820152601260248201527124b739bab33334b1b4b2b73a1022ba3432b960711b6044820152606401610d08565b601954604051636eb1769f60e11b81523360048201523060248201526001600160a01b039091169063dd62ed3e9060440160206040518083038186803b1580156123fd57600080fd5b505afa158015612411573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612435919061492e565b68056bc75e2d63100000111561248d5760405162461bcd60e51b815260206004820152601760248201527f41474c44207370656e64206e6f7420617070726f7665640000000000000000006044820152606401610d08565b6019546040516323b872dd60e01b815233600482015230602482015268056bc75e2d6310000060448201526001600160a01b03909116906323b872dd90606401602060405180830381600087803b1580156124e757600080fd5b505af11580156124fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251f9190614878565b61256b5760405162461bcd60e51b815260206004820152601d60248201527f41474c4420636f756c64206e6f74206265207472616e736665727265640000006044820152606401610d08565b6000612576600d5490565b9050612586600d80546001019055565b6000612591600d5490565b905060006125a28461ffff16611208565b905060006125b38561ffff16610e43565b905060006125c185836139a3565b905060006125d161020086615d1c565b905060006125e1868685856139db565b600e549091506126029060ff831690600160201b900463ffffffff16615c18565b600e805463ffffffff92909216600160201b0267ffffffff00000000199092169190911790556126373389888489888a613af8565b612642878285613e17565b600e546040805161ffff89811682528b16602082015260ff8416818301528715156060820152851515608082015286151560a0820152600160201b90920463ffffffff1660c0830152517ff61039a00c0d89600cf2e68be6b66798bfcebb065f4e59350531259722e6b31d9160e0908290030190a1600e54600160201b900463ffffffff16158015906126d7575061ffff8216155b156126e6576126e4612fb6565b505b600e54600160201b900463ffffffff1661272d576040517ffae7c7cc90f7db3640821bc6ee7c6e4858b63496fda86b80f842dea007e3778390600090a161272b612fb6565b505b61273b338761ffff16613f3b565b50506001600c55505050505050565b60006001600160e01b031982166380ac58cd60e01b148061277b57506001600160e01b03198216635b5e139f60e01b145b80610bfb57506301ffc9a760e01b6001600160e01b0319831614610bfb565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906127cf826118bf565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000818152600260205260408120546001600160a01b03166128815760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610d08565b600061288c836118bf565b9050806001600160a01b0316846001600160a01b031614806128c75750836001600160a01b03166128bc84610c93565b6001600160a01b0316145b806128f757506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b0316612912826118bf565b6001600160a01b03161461297a5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610d08565b6001600160a01b0382166129dc5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610d08565b6129e7838383613f55565b6129f260008261279a565b6001600160a01b0383166000908152600360205260408120805460019290612a1b908490615c01565b90915550506001600160a01b0382166000908152600360205260408120805460019290612a49908490615b4f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600e54600160481b900460ff1615612afa5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e48191a5cdd1c9a589d5d1959606a1b6044820152606401610d08565b600e54600160201b900463ffffffff1615612b275760405162461bcd60e51b8152600401610d0890615a94565b6019546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b158015612b6b57600080fd5b505afa158015612b7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba3919061492e565b90506954b40b1f852bda000000811015612bf15760405162461bcd60e51b815260206004820152600f60248201526e139bdd08195b9bdd59da081051d311608a1b6044820152606401610d08565b60008080612bfe600d5490565b601e546001600160a01b03166000908152602080526040812080549293509091612c3d90600160501b900461ffff1669021e19e0c9bab240000061400d565b612c5169021e19e0c9bab240000083615b4f565b601c546001600160a01b031660009081526020805260409020805491935090612c8f90600160501b900461ffff1669021e19e0c9bab240000061400d565b612ca369021e19e0c9bab240000084615b4f565b601d549093506001600160a01b031615612d0957601d546001600160a01b0316600090815260208052604090208054612cf190600160501b900461ffff1669021e19e0c9bab240000061400d565b612d0569021e19e0c9bab240000085615b4f565b9350505b61ffff841660009081526023602052604081205490805b60048160ff161015612e4257600f8160ff1660048110612d4257612d42615d93565b602081049190910154612d6191601f166101000a900460ff1683615b86565b91505b8160ff168961ffff161015612e30578661ffff16612dc28a61ffff168560408051446020808301919091524282840152436060830152608082019390935260a0808201949094528151808203909401845260c0019052815191012090565b612dcc9190615d3d565b612dd7906001615b4f565b9750612dfa8860108360ff1660048110612df357612df3615d93565b015461400d565b60108160ff1660048110612e1057612e10615d93565b0154612e1c9087615b4f565b955088612e2881615cbf565b995050612d64565b80612e3a81615cfc565b915050612d20565b506000612e4f868b615c01565b90508015612e99576000612e64600283615bab565b90506000612e728284615c01565b8754909150612e8c90600160501b900461ffff168361400d565b612e968a8261400d565b50505b600e805469ff0000000000000000001916600160481b1790556040517fb76e5064ebdb0730f80f1dbc7cc9bfd35de8d25c39bc13918f81c5bb6e0f221790600090a150505050505050505050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000828152602160209081526040808320546022835281842085905561ffff168084526023835292819020849055600e805460ff60401b19169055805185815291820183905281018390527f0c6471f866af3cc0cc67a48e3441efa20400dffdd1e9110ee03954c1bd37d0119060600160405180910390a1505050565b601b546040516370a0823160e01b8152306004820152600091906001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca16906370a082319060240160206040518083038186803b15801561301c57600080fd5b505afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613054919061492e565b10156130945760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420656e6f756768204c494e4b60881b6044820152606401610d08565b600061309f600d5490565b600e805460ff60401b1916600160401b179055601a54601b549192506130c491614039565b600081815260216020908152604091829020805461ffff191661ffff861690811790915582519081529081018390529193507f1d42c205e93d619991c5e1e39354edbaae3a53447001fa90cd06c5ea3c564cf2910160405180910390a15090565b6131308484846128ff565b61313c848484846141c4565b611fb05760405162461bcd60e51b8152600401610d0890615961565b606060008061316684611b21565b50505050505063ffffffff169550505060ff169350505061318a8461ffff166134eb565b613193836134eb565b61319c836134eb565b6040516020016131ae93929190614d6a565b60405160208183030381529060405292505050919050565b606060008060006131d685611b21565b5050505050505061ffff1694509450509350506131f68361ffff166134eb565b6132058263ffffffff166134eb565b6132148463ffffffff166134eb565b60405160200161322693929190615149565b6040516020818303038152906040529350505050919050565b6060600080600061324f85611b21565b5050995099509950505050505050508261328357604051806040016040528060028152602001614e6f60f01b8152506132a0565b6040518060400160405280600381526020016259657360e81b8152505b826132c557604051806040016040528060028152602001614e6f60f01b8152506132e2565b6040518060400160405280600381526020016259657360e81b8152505b8261330757604051806040016040528060028152602001614e6f60f01b815250613324565b6040518060400160405280600381526020016259657360e81b8152505b6040516020016132269392919061542d565b6060600080600061334685611b21565b9b509b5050505098505050505050508461ffff166001146133cb578061339757604051806040016040528060138152602001722a343290323930b3b7b7103634bb32b997171760691b8152506133f2565b60405180604001604052806016815260200175596f7520736c617965642074686520647261676f6e2160501b8152506133f2565b6040518060400160405280600d81526020016c466972737420737472696b652160981b8152505b6000841161340f5760405180602001604052806000815250613465565b600183151514613442576040518060400160405280600b81526020016a020bb30b4b630b136329d160ad1b815250613465565b60405180604001604052806009815260200168021b630b4b6b2b21d160bd1b8152505b60008511613482576040518060200160405280600081525061349c565b61349c613497670de0b6b3a764000087615bab565b6134eb565b600086116134b957604051806020016040528060008152506134d8565b60405180604001604052806005815260200164081051d31160da1b8152505b6040516020016132269493929190614a29565b60608161350f5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613539578061352381615ce1565b91506135329050600a83615bab565b9150613513565b60008167ffffffffffffffff81111561355457613554615da9565b6040519080825280601f01601f19166020018201604052801561357e576020820181803683370190505b5090505b84156128f757613593600183615c01565b91506135a0600a86615d3d565b6135ab906030615b4f565b60f81b8183815181106135c0576135c0615d93565b60200101906001600160f81b031916908160001a9053506135e2600a86615bab565b9450613582565b606060008060008060008060008060008060006136058d611b21565b9b509b509b509b509b509b509b509b509b509b509b5050613624614606565b6136318c61ffff166134eb565b61363d8c60ff166134eb565b61364c8c63ffffffff166134eb565b6136598c61ffff166134eb565b60405160200161366c9493929190615775565b60408051808303601f19018152919052815261368d63ffffffff89166134eb565b6136a2613497670de0b6b3a76400008a615bab565b876136b6576136b160006134eb565b6136c0565b6136c060196134eb565b876136d4576136cf60006134eb565b6136de565b6136de60326134eb565b6040516020016136f1949392919061527b565b60408051808303601f1901815291905260208201528361372d57604051806040016040528060048152602001631127379160e11b81525061374c565b60405180604001604052806005815260200164112cb2b99160d91b8152505b8361377357604051806040016040528060048152602001631127379160e11b815250613792565b60405180604001604052806005815260200164112cb2b99160d91b8152505b836137b957604051806040016040528060048152602001631127379160e11b8152506137d8565b60405180604001604052806005815260200164112cb2b99160d91b8152505b6040516020016137ea9392919061503d565b60408051808303601f190181529181528281018290528251602080850151925160009461381a949290910161498f565b60408051601f198184030181529190529f9e505050505050505050505050505050565b80516060908061385d575050604080516020810190915260008152919050565b6000600361386c836002615b4f565b6138769190615bab565b613881906004615bbf565b90506000613890826020615b4f565b67ffffffffffffffff8111156138a8576138a8615da9565b6040519080825280601f01601f1916602001820160405280156138d2576020820181803683370190505b5090506000604051806060016040528060408152602001615df9604091399050600181016020830160005b8681101561395e576003818a01810151603f601282901c8116860151600c83901c8216870151600684901c831688015192909316870151600891821b60ff94851601821b92841692909201901b91160160e01b8352600490920191016138fd565b506003860660018114613978576002811461398957613995565b613d3d60f01b600119830152613995565b603d60f81b6000198301525b505050918152949350505050565b60008061ffff8416158015906139b7575082155b156139d4576139c584611b21565b50909a50505050505050505050505b9392505050565b6000806001841515146139ef5760006139f2565b60325b600186151514613a03576000613a06565b60195b613a109190615b86565b90506000613a1f601983615b86565b90506000613a2e8260c8615c35565b90506000613a3c868a615bde565b61ffff8082166000908152602360205260408120549293509060ff8087169190861690613aa7908e168560408051446020808301919091524282840152436060830152608082019390935260a0808201949094528151808203909401845260c0019052815191012090565b613ab19190615d3d565b613abb9190615b4f565b600e54909150600160201b900463ffffffff1660ff82161115613aea5750600e54600160201b900463ffffffff165b9a9950505050505050505050565b61ffff85166000908152601f602090815260408083206001600160a01b03808c1685529280529220601c54909116613b4657601c80546001600160a01b0319166001600160a01b038b161790555b601c546001600160a01b0316600090815260208052604081208254909160ff891691849190613b7c90849063ffffffff16615b67565b825463ffffffff9182166101009390930a928302919092021990911617905550815461ffff808a16600160501b0261ffff60501b19909216919091178084556001918491600891613bd7918591600160401b90910416615b29565b825461ffff9182166101009390930a9283029190920219909116179055508054825463ffffffff91821691161115613c2557601c80546001600160a01b0319166001600160a01b038c161790555b878360000160016101000a81548161ffff021916908361ffff160217905550898360010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550888360000160036101000a81548161ffff021916908361ffff160217905550868360000160006101000a81548160ff021916908360ff1602179055508160000160009054906101000a900463ffffffff168360000160076101000a81548163ffffffff021916908363ffffffff1602179055508160000160089054906101000a900461ffff168360000160056101000a81548161ffff021916908361ffff160217905550600e60049054906101000a900463ffffffff1683600001600b6101000a81548163ffffffff021916908363ffffffff1602179055508583600001600f6101000a81548160ff021916908315150217905550848360000160106101000a81548160ff021916908315150217905550838360000160116101000a81548160ff021916908315150217905550600e60049054906101000a900463ffffffff1663ffffffff166000148360000160126101000a81548160ff0219169083151502179055508260000160129054906101000a900460ff161515600115151415613e0b57601e80546001600160a01b0319166001600160a01b038c161790555b50505050505050505050565b61ffff83166000908152601f6020908152604080832060018101546001600160a01b0390811685529280529220601d54909116613e73576001820154601d80546001600160a01b0319166001600160a01b039092169190911790555b601d546001600160a01b0316600090815260208052604090208315156001148015613eab57508254600160881b900460ff1615156001145b15613f3357815460ff8616908390600490613ed4908490600160201b900463ffffffff16615b67565b82546101009290920a63ffffffff81810219909316918316021790915582548454600160201b91829004831691900490911611159050613f33576001830154601d80546001600160a01b0319166001600160a01b039092169190911790555b505050505050565b611a278282604051806020016040528060008152506142ce565b6001600160a01b038316613fb057613fab81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b613fd3565b816001600160a01b0316836001600160a01b031614613fd357613fd38382614301565b6001600160a01b038216613fea57610e3e8161439e565b826001600160a01b0316826001600160a01b031614610e3e57610e3e828261444d565b61ffff821660009081526024602052604081208054839290614030908490615b4f565b90915550505050565b60007f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316634000aea07f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952848660006040516020016140a9929190918252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016140d693929190615927565b602060405180830381600087803b1580156140f057600080fd5b505af1158015614104573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141289190614878565b506000838152600a6020818152604080842054815180840189905280830186905230606082015260808082018390528351808303909101815260a090910190925281519183019190912093879052919052614184906001615b4f565b6000858152600a60205260409020556128f78482604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60006001600160a01b0384163b156142c657604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906142089033908990889088906004016158f4565b602060405180830381600087803b15801561422257600080fd5b505af1925050508015614252575060408051601f3d908101601f1916820190925261424f918101906148ed565b60015b6142ac573d808015614280576040519150601f19603f3d011682016040523d82523d6000602084013e614285565b606091505b5080516142a45760405162461bcd60e51b8152600401610d0890615961565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506128f7565b5060016128f7565b6142d88383614491565b6142e560008484846141c4565b610e3e5760405162461bcd60e51b8152600401610d0890615961565b6000600161430e84611936565b6143189190615c01565b60008381526007602052604090205490915080821461436b576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906143b090600190615c01565b600083815260096020526040812054600880549394509092849081106143d8576143d8615d93565b9060005260206000200154905080600883815481106143f9576143f9615d93565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061443157614431615d7d565b6001900381819060005260206000200160009055905550505050565b600061445883611936565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160a01b0382166144e75760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610d08565b6000818152600260205260409020546001600160a01b03161561454c5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610d08565b61455860008383613f55565b6001600160a01b0382166000908152600360205260408120805460019290614581908490615b4f565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60405180608001604052806004905b60608152602001906001900390816145ee5790505090565b6040805160608082019092529081526002602082016145ee565b60006020828403121561463257600080fd5b81356139d481615dbf565b60006020828403121561464f57600080fd5b81516139d481615dbf565b6000806040838503121561466d57600080fd5b823561467881615dbf565b9150602083013561468881615dbf565b809150509250929050565b6000806000606084860312156146a857600080fd5b83356146b381615dbf565b925060208401356146c381615dbf565b929592945050506040919091013590565b600080600080608085870312156146ea57600080fd5b84356146f581615dbf565b935060208581013561470681615dbf565b935060408601359250606086013567ffffffffffffffff8082111561472a57600080fd5b818801915088601f83011261473e57600080fd5b81358181111561475057614750615da9565b614762601f8201601f19168501615af8565b9150808252898482850101111561477857600080fd5b808484018584013760008482840101525080935050505092959194509250565b600080604083850312156147ab57600080fd5b82356147b681615dbf565b9150602083013561468881615dd4565b600080604083850312156147d957600080fd5b82356147e481615dbf565b946020939093013593505050565b600060a0828403121561480457600080fd5b82601f83011261481357600080fd5b60405160a0810181811067ffffffffffffffff8211171561483657614836615da9565b604052808360a0810186101561484b57600080fd5b60005b600581101561486d57815183526020928301929091019060010161484e565b509195945050505050565b60006020828403121561488a57600080fd5b81516139d481615dd4565b6000602082840312156148a757600080fd5b5035919050565b600080604083850312156148c157600080fd5b50508035926020909101359150565b6000602082840312156148e257600080fd5b81356139d481615de2565b6000602082840312156148ff57600080fd5b81516139d481615de2565b60006020828403121561491c57600080fd5b813561ffff811681146139d457600080fd5b60006020828403121561494057600080fd5b5051919050565b6000815180845261495f816020860160208601615c58565b601f01601f19169290920160200192915050565b60008151614985818560208601615c58565b9290920192915050565b600084516149a1818460208901615c58565b8451908301906149b5818360208901615c58565b84519101906149c8818360208801615c58565b0195945050505050565b600085516149e4818460208a01615c58565b8551908301906149f8818360208a01615c58565b8551910190614a0b818360208901615c58565b8451910190614a1e818360208801615c58565b019695505050505050565b60008551614a3b818460208a01615c58565b80830190507f3c2f746578743e3c7465787420783d2233302220793d223331352220636c6173815268399e913130b9b2911f60b91b60208201528551614a88816029840160208a01615c58565b8551910190614a9e816029840160208901615c58565b8451910190614ab4816029840160208801615c58565b7f3c2f746578743e3c7265637420783d223332322e322220793d223332352e3222602992909101918201527f207472616e73666f726d3d226d617472697828302e37333432202d302e36373860498201527f3920302e3637383920302e37333432202d3133362e33383136203330372e393760698201527f383129222066696c6c3d2223463242313338222077696474683d22352e39222060898201527f6865696768743d22352e39222f3e3c7265637420783d223332362e362220793d60a98201527f223332312e3222207472616e73666f726d3d226d617472697828302e3733343260c98201527f202d302e3637383920302e3637383920302e37333432202d3133322e3530373560e98201527f203330392e3835363329222066696c6c3d2223423738333330222077696474686101098201527f3d22352e3922206865696768743d22352e39222f3e3c7265637420783d2233326101298201527f362e322220793d223332392e3622207472616e73666f726d3d226d61747269786101498201527f28302e37333432202d302e3637383920302e3637383920302e37333432202d316101698201527f33382e32353938203331312e3835323129222066696c6c3d22234237383333306101898201527f222077696474683d22352e3922206865696768743d22352e39222f3e3c7265636101a98201527f7420783d223333302e362220793d223332352e3622207472616e73666f726d3d6101c98201527f226d617472697828302e37333432202d302e3637383920302e3637383920302e6101e98201527f37333432202d3133342e33383537203331332e3733303429222066696c6c3d226102098201527f23463242313338222077696474683d22352e3922206865696768743d22352e396102298201526811179f1e17b9bb339f60b91b610249820152610252019695505050505050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f73766722207072657365727665417370656374526174696f3d22784d6960208201527f6e594d696e206d656574222076696577426f783d22302030203335302033353060408201527f223e3c7374796c653e2e62617365207b2066696c6c3a20234646464346433b2060608201527f666f6e742d66616d696c793a206d6f6e6f73706163653b20666f6e742d73697a60808201527f653a20313470783b207d202e7469746c65207b2066696c6c3a2023464646434660a08201527f433b20666f6e742d66616d696c793a206d6f6e6f73706163653b20666f6e742d60c08201527f73697a653a20323470783b20746578742d616e63686f723a206d6964646c653b60e08201527f20646f6d696e616e742d626173656c696e653a206d6964646c653b207d3c2f736101008201527f74796c653e3c726563742077696474683d223130302522206865696768743d226101208201527f31303025222066696c6c3d222330303346363322202f3e3c7465787420783d226101408201527f3137352220793d2233352220636c6173733d227469746c65223e5155455354536101608201527f20464f52204c4f4f543c2f746578743e3c7465787420783d2233302220793d226101808201527501c1a911031b630b9b99e913130b9b2911f2a3ab937160551b6101a0820152600061503461502e614fdf614fd9614f966101b687018a614973565b7f3c2f746578743e3c7465787420783d2233302220793d223131352220636c61738152700399e913130b9b2911f2230b6b0b3b29d1607d1b602082015260310190565b87614973565b7f2048503c2f746578743e3c7465787420783d2233302220793d2231333522206381527f6c6173733d2262617365223e52656d61696e696e673a20000000000000000000602082015260370190565b84614973565b95945050505050565b7f7d2c7b2274726169745f74797065223a202250726f766964656420537570706f81526d0393a111610113b30b63ab2911d160951b60208201526000845161508c81602e850160208901615c58565b7f7d2c7b2274726169745f74797065223a202241474c4420436c61696d6564222c602e9184019182015269010113b30b63ab2911d160b51b604e82015284516150dc816058840160208901615c58565b7f7d2c7b2274726169745f74797065223a2022447261676f6e20536c6179657222605892909101918201526a01610113b30b63ab2911d160ad1b6078820152835161512e816083840160208801615c58565b607d60f81b6083929091019182015260840195945050505050565b7f2048503c2f746578743e3c7465787420783d2233302220793d2231353522206381527f6c6173733d2262617365223e4c6f6f74204261673a20230000000000000000006020820152600084516151a7816037850160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223137352220636c61736037918401918201527f733d2262617365223e5475726e7320506c617965643a200000000000000000006057820152845161520a81606e840160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223139352220636c6173606e92909101918201527f733d2262617365223e546f74616c2044616d6167653a20000000000000000000608e820152835161526e8160a5840160208801615c58565b0160a50195945050505050565b7f7d2c7b2274726169745f74797065223a2022447261676f6e204850222c202276815266030b63ab2911d160cd1b6020820152600085516152c3816027850160208a01615c58565b7f7d2c7b2274726169745f74797065223a202241474c4420417661696c61626c656027918401918201527f222c2022646973706c61795f74797065223a20226e756d626572222c202276616047820152650363ab2911d160d51b6067820152855161533581606d840160208a01615c58565b7f7d2c7b2274726169745f74797065223a202244616d61676520426f6f7374222c606d92909101918201527f2022646973706c61795f74797065223a2022626f6f73745f6e756d626572222c608d82015269010113b30b63ab2911d160b51b60ad82015284516153ac8160b7840160208901615c58565b61542161541b60b7838501017f7d2c7b2274726169745f74797065223a2022537570706f727420426f6f73742281527f2c2022646973706c61795f74797065223a2022626f6f73745f6e756d6265722260208201526a01610113b30b63ab2911d160ad1b6040820152604b0190565b86614973565b98975050505050505050565b7f3c2f746578743e3c7465787420783d2233302220793d223232352220636c617381527f733d2262617365223e44616d61676520426f6f73743a2000000000000000000060208201526000845161548b816037850160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223234352220636c61736037918401918201527f733d2262617365223e537570706f727420426f6f73743a200000000000000000605782015284516154ee81606f840160208901615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223236352220636c6173606f92909101918201527f733d2262617365223e50726f766964656420537570706f72743a200000000000608f82015283516155528160aa840160208801615c58565b7f3c2f746578743e3c7465787420783d2233302220793d223239352220636c617360aa929091019182015268399e913130b9b2911f60b91b60ca82015260d30195945050505050565b6e03d913730b6b2911d10112a3ab9371608d1b815283516000906155c681600f850160208901615c58565b71222c202261747472696275746573223a205b60701b600f9184019182015284516155f8816021840160208901615c58565b7f5d2c20226465736372697074696f6e223a202251756573747320666f72204c6f602192909101918201527f6f742061726520626174746c65207265636f7264732073746f726564206f6e2d60418201527f636861696e20666f722061204d554420746f20736c6179206120647261676f6e60618201527f20746861742773207261766167696e6720612076696c6c6167652e20506c617960818201527f657273206d75737420776f726b20746f67657468657220746f2064656665617460a18201527f20697420616e64207265617020746865207265776172647321222c2022696d6160c18201527f6765223a2022646174613a696d6167652f7376672b786d6c3b6261736536342c60e1820152615726615718610101830186614973565b61227d60f01b815260020190565b9695505050505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081526000825161576881601d850160208701615c58565b91909101601d0192915050565b7f7b2274726169745f74797065223a20224c6f6f74222c202276616c7565223a208152601160f91b6020820152600085516157b7816021850160208a01615c58565b7f227d2c7b2274726169745f74797065223a202244616d616765204465616c74226021918401918201526a01610113b30b63ab2911d160ad1b6041820152855161580881604c840160208a01615c58565b7f7d2c7b2274726169745f74797065223a202243756d756c61746976652044616d604c92909101918201527f616765204465616c74222c2022646973706c61795f74797065223a20226e756d606c8201526e03132b9111610113b30b63ab2911d1608d1b608c8201819052855161588681609b850160208a01615c58565b7f7d2c7b2274726169745f74797065223a202243756d756c617469766520547572609b93909101928301527f6e7320506c61796564222c2022646973706c61795f74797065223a20226e756d60bb83015260db8201526158e960ea820185614973565b979650505050505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061572690830184614947565b60018060a01b03841681528260208201526060604082015260006150346060830184614947565b6020815260006139d46020830184614947565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252600a9082015269125b9d985b1a5908125160b21b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526019908201527f57616974696e6720666f722056524620746f2072657475726e00000000000000604082015260600190565b602080825260139082015272223930b3b7b71034b9903737ba1039b630b4b760691b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b604051601f8201601f1916810167ffffffffffffffff81118282101715615b2157615b21615da9565b604052919050565b600061ffff808316818516808303821115615b4657615b46615d51565b01949350505050565b60008219821115615b6257615b62615d51565b500190565b600063ffffffff808316818516808303821115615b4657615b46615d51565b600060ff821660ff84168060ff03821115615ba357615ba3615d51565b019392505050565b600082615bba57615bba615d67565b500490565b6000816000190483118215151615615bd957615bd9615d51565b500290565b600061ffff83811690831681811015615bf957615bf9615d51565b039392505050565b600082821015615c1357615c13615d51565b500390565b600063ffffffff83811690831681811015615bf957615bf9615d51565b600060ff821660ff841680821015615c4f57615c4f615d51565b90039392505050565b60005b83811015615c73578181015183820152602001615c5b565b83811115611fb05750506000910152565b600181811c90821680615c9857607f821691505b60208210811415615cb957634e487b7160e01b600052602260045260246000fd5b50919050565b600061ffff80831681811415615cd757615cd7615d51565b6001019392505050565b6000600019821415615cf557615cf5615d51565b5060010190565b600060ff821660ff811415615d1357615d13615d51565b60010192915050565b600061ffff80841680615d3157615d31615d67565b92169190910692915050565b600082615d4c57615d4c615d67565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461172857600080fd5b801515811461172857600080fd5b6001600160e01b03198116811461172857600080fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220ef0216e22d8311343546cf1c3889cde1f71c1dd61c26a64afb6fd00c2f21964764736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952000000000000000000000000514910771af9ca656af840dff83e8264ecf986caaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af4450000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000ff9c1b15b16263c61d017ee9f65c50e4ae0113d70000000000000000000000003eb43b1545a360d1d065cb7539339363dfd445f300000000000000000000000032353a6c91143bfd6c7d363b546e62a9a2489a20
-----Decoded View---------------
Arg [0] : vrfCoordinator (address): 0xf0d54349aDdcf704F77AE15b96510dEA15cb7952
Arg [1] : link (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [2] : keyHash (bytes32): 0xaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445
Arg [3] : fee (uint256): 2000000000000000000
Arg [4] : startHP (uint32): 1000000
Arg [5] : _lootContractAddress (address): 0xFF9C1b15B16263C61d017ee9F65C50e4AE0113D7
Arg [6] : _lootComponentsContractAddress (address): 0x3eb43b1545a360d1D065CB7539339363dFD445F3
Arg [7] : _agldContractAddress (address): 0x32353A6C91143bfd6C7d363B546e62a9A2489A20
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952
Arg [1] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [2] : aa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445
Arg [3] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [4] : 00000000000000000000000000000000000000000000000000000000000f4240
Arg [5] : 000000000000000000000000ff9c1b15b16263c61d017ee9f65c50e4ae0113d7
Arg [6] : 0000000000000000000000003eb43b1545a360d1d065cb7539339363dfd445f3
Arg [7] : 00000000000000000000000032353a6c91143bfd6c7d363b546e62a9a2489a20
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.