Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ItemCommonConsumable
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 150 runs
Other Settings:
istanbul EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
/**
▒▓▒ ▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▒ ▒▒▒▒▓▓▓▒▓▓▓▓▓▓▓██▓
▒██▒▓▓▓▓█▓██████████████████▓ ▒▒▒▓███████████████▒
▒██▒▓█████████████████████▒ ▒▓██████████▓███████
▒███████████▓▒ ▒███▓▓██████▓
█████████▒ ▒▓▒▓███████▒
███████▓ ▒▒▒▒▒▓▓█▓▒ ▓█▓████████
▒▒▒▒▒ ▒▒▒▒▓▓▓█████▒ ▓█████████▓
▒▓▓▓▒▓██████▓ ▒▓▓████████▒
▒██▓▓▓███████▒ ▒▒▓███▓████
▒███▓█████▒ ▒▒█████▓██▓
██████▓ ▒▒▒▓██▓██▓█████▒
▒▒▓▓▒ ▒██▓▒▓▓████████
▓█████▓███████▓
██▓▓██████████▒
▒█████████████
███████████▓
▒▓▓▓▓▓▓▒▓ ▒█████████▒ ▒▓▓
▒▓█▒ ▒▒█▒▒ ▓██████ ▒▒▓▓▒
▒▒█▒ ▓▒ ▒████ ▒▓█▓█▓▒
▓▒██▓▒ ██ ▒▓█▓▓▓██▒
▓█▓▓▓▓▓█▓▓▓▒ ▒▒▒ ▒▒▒▓▓▓▓▒▓▒▒▓▒▓▓▓▓▓▓▓▓▒ ▒▓█▒ ▒▓▒▓█▓
▒▓█▓▓▓▓▓▓▓▓▓▓▒ ▒▒▒▓▒ ▒▒▒▓▓ ▓▓ ▓▓█▓ ▒▒▓▓ ▒▒█▒ ▒▓▒▓█▓
▒▒▓▓▓▒▓▒ ▒▓▓▓▒█▒ ▒▒▒█▒ ▒▒█▓▒▒▒▓▓▓▒ ▓██▓▓▓▓▓▓▓███▓
▒ ▒▓▓█▓ ▒▓▓▓▓█▓█▓ ▒█▓▓▒ ▓▓█▓▒▓█▓▒▒ ▓█▓ ▓███▓
▓▓▒ ▒▒▓▓█▓▒▒▓█▒ ▒▓██▓ ▓██▓▒ ▒█▓ ▓▓██ ▒▓▓▓▒▒▓█▓ ▒▓████▒
██▓▓▒▒▒▒▓▓███▓▒ ▒▓▓▓▓▒▒ ▒▓▓▓▓▓▓▓▒▒▒▓█▓▓▓▓█▓▓▒▒▓▓▓▓▓▒ ▒▓████▓▒ ▓▓███████▓▓▒
*/
pragma solidity 0.8.23;
import "../base/item/ConsumableItemBase.sol";
contract ItemCommonConsumable is ConsumableItemBase {
// ---- CONSTANTS ----
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant override VERSION = "1.0.0";
function itemMetaType() external pure override returns (ItemMetaType) {
return ItemMetaType.CONSUMABLE_ITEM;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./ItemBase.sol";
import "../../interfaces/IConsumableItem.sol";
abstract contract ConsumableItemBase is ItemBase, IConsumableItem {
using EnumerableMap for EnumerableMap.UintToIntMap;
using StructLib for EnumerableMap.UintToIntMap;
// ---- CONSTANTS ----
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant CONSUMABLE_ITEM_BASE_VERSION = "1.0.1";
// ---- VARIABLES ----
bool internal _consumableItemInited;
mapping(uint => EnumerableMap.UintToIntMap) internal _itemsConsumableAttributesPositive;
mapping(uint => EnumerableMap.UintToIntMap) internal _itemsConsumableAttributesNegative;
mapping(uint => IStatController.ChangeableStats) internal _itemsConsumableStats;
GenerateConsumableInfo internal _consumableGenerateInfo;
IStatController.ChangeableStats internal _consumableStatsInfo;
/// @dev This empty reserved space is put in place to allow future versions to add new
/// variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[44] private __gap;
// ---- EVENTS ----
event Used(uint id, address hero, uint heroId);
event ConsumableInfoChanged(GenerateConsumableInfo info, IStatController.ChangeableStats stats);
// ---- INITIALIZER ----
// init implementation
constructor() {_consumableItemInited = true;}
// ---- VIEWS ----
function isConsumableItem() public pure override returns (bool) {
return true;
}
function consumableAttributesAndStats(uint tokenId)
external view override returns (uint[] memory positive, uint[] memory negative, IStatController.ChangeableStats memory stats) {
return (_itemsConsumableAttributesPositive[tokenId].flat(), _itemsConsumableAttributesNegative[tokenId].flat(), _itemsConsumableStats[tokenId]);
}
// ---- GOV ACTIONS ----
function setConsumableInfo(GenerateConsumableInfo memory consumableGenerateInfo_, IStatController.ChangeableStats memory consumableStatsInfo_) external {
onlyDeployer();
_consumableGenerateInfo = consumableGenerateInfo_;
_consumableStatsInfo = consumableStatsInfo_;
_consumableItemInited = true;
emit ConsumableInfoChanged(consumableGenerateInfo_, consumableStatsInfo_);
}
// ---- ACTIONS ----
function use(uint tokenId, address heroToken, uint heroTokenId) external {
IController c = IController(controller());
onlyOwner(tokenId);
require(_isNotSmartContract(), "EOA");
require(!c.onPause(), 'paused');
IStatController _statController = IStatController(c.statController());
ItemLib.checkRequirements(_statController, heroToken, heroTokenId, _requirements);
_statController.registerConsumableUsage(heroToken, heroTokenId, address(this));
_statController.changeCurrentStats(heroToken, heroTokenId, _itemsConsumableStats[tokenId], true);
_statController.changeBonusAttributes(IStatController.ChangeAttributesInfo({
heroToken: heroToken,
heroTokenId: heroTokenId,
changeAttributes: _itemsConsumableAttributesPositive[tokenId].flat(),
increase: true,
temporally: true
}));
_statController.changeBonusAttributes(IStatController.ChangeAttributesInfo({
heroToken: heroToken,
heroTokenId: heroTokenId,
changeAttributes: _itemsConsumableAttributesNegative[tokenId].flat(),
increase: false,
temporally: true
}));
_destroy(tokenId);
emit Used(tokenId, heroToken, heroTokenId);
}
function _afterMint(uint tokenId) internal override {
super._afterMint(tokenId);
_itemsConsumableStats[tokenId] = _generateConsumableItem(_itemsConsumableAttributesPositive[tokenId], _itemsConsumableAttributesNegative[tokenId], tokenId);
}
function _generateConsumableItem(EnumerableMap.UintToIntMap storage attributesPos, EnumerableMap.UintToIntMap storage attributesNeg, uint /*tokenId*/) internal virtual returns (IStatController.ChangeableStats memory) {
IItemCalculator itemCalculator = IItemCalculator(IController(controller()).itemCalculator());
(IItem.GenerateInfo memory posInfo, IItem.GenerateInfo memory negInfo) = itemCalculator.consumableInfoToGenerateInfo(_consumableGenerateInfo);
(uint[] memory idsPos, uint[] memory valuesPos,) = itemCalculator.generateAttributes(posInfo, defaultRarity);
for (uint i; i < valuesPos.length;) {
uint value = valuesPos[i];
uint index = idsPos[i];
if (value != 0) {
attributesPos.setUint(index, value);
}
unchecked{++i;}
}
(uint[] memory idsNeg, uint[] memory valuesNeg,) = itemCalculator.generateAttributes(negInfo, defaultRarity);
for (uint i; i < valuesNeg.length;) {
uint value = valuesNeg[i];
uint index = idsNeg[i];
if (value != 0) {
attributesNeg.setUint(index, value);
}
unchecked{++i;}
}
return _consumableStatsInfo;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "../NftBase.sol";
import "../../openzeppelin/IERC20.sol";
import "../../openzeppelin/SafeERC20.sol";
import "../../openzeppelin/Math.sol";
import "../../interfaces/IItem.sol";
import "../../interfaces/IOracle.sol";
import "../../interfaces/IHero.sol";
import "../../interfaces/IGameToken.sol";
import "../../interfaces/IStatController.sol";
import "../../lib/StatLib.sol";
import "../../lib/StructLib.sol";
import "../../lib/ItemLib.sol";
import "../../interfaces/IItemCalculator.sol";
import "../../interfaces/IReinforcementController.sol";
import "../../interfaces/IChamberController.sol";
import "../../interfaces/ITreasury.sol";
abstract contract ItemBase is NftBase, IItem {
using SafeERC20 for IERC20;
using EnumerableMap for EnumerableMap.UintToIntMap;
using StructLib for EnumerableMap.UintToIntMap;
// ---- CONSTANTS ----
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant ITEM_BASE_VERSION = "1.0.3";
// ---- VARIABLES ----
bool internal _itemInited;
address public override augmentToken;
uint public override augmentTokenAmount;
uint public override itemLevel;
uint public override itemType;
uint public override baseDurability;
mapping(uint => EnumerableMap.UintToIntMap) internal _itemAttributes;
mapping(uint => EnumerableMap.UintToIntMap) internal _negativeItemAttributes;
mapping(uint => uint) public override itemRarity;
mapping(uint => bool) public override equipped;
mapping(uint => uint) public override augmentationLevel;
mapping(uint => string) internal _itemUriByRarity;
mapping(uint => uint) public override itemDurability;
GenerateInfo internal _generateInfo;
GenerateInfo internal _negativeGenerateInfo;
IStatController.CoreAttributes internal _requirements;
uint internal defaultRarity;
/// @dev itemId => heroAdr => heroId
mapping(uint => mapping(address => uint)) public override equippedOn;
/// @dev This empty reserved space is put in place to allow future versions to add new
/// variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[36] private __gap;
// ---- EVENTS ----
event UriByRarityChanged(string uri, uint rarity);
event Minted(uint id, uint rarity);
event Equipped(uint tokenId, address heroToken, uint heroTokenId, uint itemSlot);
event TakenOff(
uint tokenId,
address heroToken,
uint heroTokenId,
uint itemSlot,
address destination
);
event Augmented(uint id, uint consumedId, uint augmentationLevel);
event NotAugmented(uint id, uint consumedId, uint augmentationLevel);
event Destroyed(uint id);
event ItemRepaired(uint tokenId, uint consumedItemId);
event RequirementsChanged(IStatController.CoreAttributes requirements);
event GenInfoChanged(GenerateInfo info, GenerateInfo negativeInfo);
event ReduceDurability(uint id, uint newDurability);
event BaseDurabilityChanged(uint value);
// ---- INITIALIZER ----
// init implementation
constructor() {_itemInited = true;}
function initItem(
address controller_,
string memory name_,
string memory symbol_,
string memory uri_,
address augmentToken_,
uint augmentTokenAmount_,
// Level in range 1-99. Reducing durability in low level dungeons. lvl/5+1 = biome
uint itemLevel_,
ItemType itemType_,
uint baseDurability_
) external {
_initializer();
__NftBase_init(name_, symbol_, controller_, uri_);
augmentToken = augmentToken_;
augmentTokenAmount = augmentTokenAmount_;
itemLevel = itemLevel_;
itemType = uint(itemType_);
baseDurability = baseDurability_;
_finishInitializer();
}
// ---- RESTRICTIONS ----
function onlyDungeon() internal view {
require(IController(controller()).validDungeons(msg.sender), "!dungeon");
}
function onlyOwner(uint tokenId) internal view {
require(ownerOf(tokenId) == _msgSender(), "forbidden");
}
function onlyHeroOrValidContract(IController c) internal view {
require(c.validHeroes(msg.sender) || c.storyController() == msg.sender, "forbidden");
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override {
require(!equipped[tokenId], "equipped");
super._beforeTokenTransfer(from, to, tokenId);
}
// ---- VIEWS ----
function isOwner(address spender, uint tokenId) external view override returns (bool) {
return ownerOf(tokenId) == spender;
}
function isItem() external pure override returns (bool) {
return true;
}
function isAttackItem() external pure override virtual returns (bool) {
return false;
}
function isBuffItem() external pure override virtual returns (bool) {
return false;
}
function isConsumableItem() public pure virtual override returns (bool) {
return false;
}
function itemAttributes(uint tokenId) external view override returns (uint[] memory) {
return _itemAttributes[tokenId].flat();
}
function negativeItemAttributes(uint tokenId) external view override returns (uint[] memory) {
return _negativeItemAttributes[tokenId].flat();
}
function _specificURI(uint tokenId) internal view override returns (string memory) {
return _itemUriByRarity[itemRarity[tokenId]];
}
function requirementAttributes() public view override returns (IStatController.CoreAttributes memory) {
return _requirements;
}
function score(uint tokenId) external view override returns (uint) {
return IItemCalculator(IController(controller()).itemCalculator()).score(_itemAttributes[tokenId].flat(), baseDurability);
}
// ---- GOV ACTIONS ----
function setItemUriByRarity(string memory uri, uint rarity) external {
onlyDeployer();
_itemUriByRarity[rarity] = uri;
emit UriByRarityChanged(uri, rarity);
}
function setItemMeta(
GenerateInfo memory _info,
GenerateInfo memory _negativeInfo,
uint strengthReq,
uint dexterityReq,
uint vitalityReq,
uint energyReq,
uint defaultRarity_
) external {
onlyDeployer();
require(_info.minRandomAttributes < 2, "wrong min");
_generateInfo = _info;
_negativeGenerateInfo = _negativeInfo;
_requirements = IStatController.CoreAttributes(
strengthReq,
dexterityReq,
vitalityReq,
energyReq
);
defaultRarity = defaultRarity_;
_itemInited = true;
emit RequirementsChanged(IStatController.CoreAttributes(
strengthReq,
dexterityReq,
vitalityReq,
energyReq
));
emit GenInfoChanged(_info, _negativeInfo);
}
function setBaseDurability(uint value) external {
onlyDeployer();
baseDurability = value;
emit BaseDurabilityChanged(value);
}
// ---- DUNGEON ACTIONS ----
function mint() external override returns (uint tokenId) {
onlyDungeon();
return _mintInternal();
}
function _mintInternal() internal returns (uint tokenId) {
tokenId = _incrementAndGetId();
_safeMint(_msgSender(), tokenId);
IItemCalculator itemCalculator = IItemCalculator(IController(controller()).itemCalculator());
uint rarity = ItemLib.generateAttributes(itemCalculator, _itemAttributes[tokenId], _generateInfo, defaultRarity);
ItemLib.generateAttributes(itemCalculator, _negativeItemAttributes[tokenId], _negativeGenerateInfo, 1);
itemRarity[tokenId] = rarity;
itemDurability[tokenId] = baseDurability;
_afterMint(tokenId);
emit Minted(tokenId, rarity);
}
// ---- EOA ACTIONS ----
// an item must not be equipped
function equip(uint tokenId, address heroToken, uint heroTokenId, uint itemSlot) external override {
IController _controller = IController(controller());
onlyOwner(tokenId);
require(_isNotSmartContract(), "EOA");
require(!equipped[tokenId], "equipped");
require(!_controller.onPause(), 'paused');
require(IHero(heroToken).payToken() != address(0), "forbidden");
ItemLib.equip(
_itemAttributes,
_negativeItemAttributes,
ItemLib.EquipContext({
sender: _msgSender(),
_controller: _controller,
tokenId: tokenId,
heroToken: heroToken,
heroTokenId: heroTokenId,
itemSlot: itemSlot,
_itemType: itemType,
_baseDurability: baseDurability,
_itemDurability: itemDurability[tokenId],
requirements: _requirements
})
);
// transfer item to hero
_safeTransfer(_msgSender(), heroToken, tokenId, '');
// need to equip after transfer for properly checks
equipped[tokenId] = true;
equippedOn[tokenId][heroToken] = heroTokenId;
emit Equipped(tokenId, heroToken, heroTokenId, itemSlot);
}
/// @dev Repair durability.
function repairDurability(uint tokenId, uint consumedItemId) external override {
IController c = IController(controller());
require(_isNotSmartContract(), "EOA");
onlyOwner(tokenId);
onlyOwner(consumedItemId);
uint _baseDurability = baseDurability;
require(_baseDurability != 0, "!durability");
require(!equipped[tokenId] && !equipped[consumedItemId], "equipped");
require(!c.onPause(), 'paused');
_destroy(consumedItemId);
ItemLib.sendFee(IController(controller()), augmentToken, FeeType.REPAIR, _msgSender(), augmentTokenAmount / 10);
itemDurability[tokenId] = _baseDurability;
emit ItemRepaired(tokenId, consumedItemId);
}
function augment(uint tokenId, uint consumedItemId) external {
require(_isNotSmartContract(), "EOA");
onlyOwner(tokenId);
onlyOwner(consumedItemId);
require(!isConsumableItem(), "consumable");
_destroy(consumedItemId);
(bool success, uint agLevel) = ItemLib.augment(
_msgSender(),
augmentToken,
augmentTokenAmount,
tokenId,
consumedItemId,
augmentationLevel[tokenId],
IController(controller()),
equipped,
_itemAttributes
);
if (success) {
_additionalAugment(tokenId);
augmentationLevel[tokenId] = agLevel;
emit Augmented(tokenId, consumedItemId, agLevel);
} else {
_destroy(tokenId);
emit NotAugmented(tokenId, consumedItemId, agLevel);
}
}
// ---- HERO ACTIONS ----
// assume the item is equipped to the hero and the hero is owner
/// @dev Only hero contract can do it. Equipped items should be on hero.
function takeOff(
uint tokenId,
address heroToken,
uint heroTokenId,
uint itemSlot,
address destination,
bool broken
) external override {
IController c = IController(controller());
onlyHeroOrValidContract(c);
require(equipped[tokenId] && equippedOn[tokenId][heroToken] == heroTokenId, "!equipped");
uint _itemType = itemType;
require(_itemType != 0, "consumable");
IStatController statController = IStatController(c.statController());
statController.changeHeroItemSlot(
heroToken,
heroTokenId,
_itemType,
itemSlot,
address(this),
tokenId,
false
);
if (broken) {
itemDurability[tokenId] = 0;
}
statController.changeBonusAttributes(IStatController.ChangeAttributesInfo({
heroToken: heroToken,
heroTokenId: heroTokenId,
changeAttributes: _itemAttributes[tokenId].flat(),
increase: false,
temporally: false
}));
statController.changeBonusAttributes(IStatController.ChangeAttributesInfo({
heroToken: heroToken,
heroTokenId: heroTokenId,
changeAttributes: _negativeItemAttributes[tokenId].flat(),
increase: true,
temporally: false
}));
// need to take off before transfer for properly checks
equipped[tokenId] = false;
equippedOn[tokenId][heroToken] = 0;
_safeTransfer(heroToken, destination, tokenId, '');
emit TakenOff(tokenId, heroToken, heroTokenId, itemSlot, destination);
}
/// @dev Only hero contract can do it. Reduce after a battle.
function reduceDurability(uint tokenId, uint dungeonBiomeLevel) external override returns (uint) {
IController _controller = IController(controller());
onlyHeroOrValidContract(_controller);
IItemCalculator itemCalculator = IItemCalculator(_controller.itemCalculator());
uint newDurability = itemCalculator.calcReduceDurability(dungeonBiomeLevel, itemDurability[tokenId], itemLevel, itemType);
itemDurability[tokenId] = newDurability;
emit ReduceDurability(tokenId, newDurability);
return newDurability;
}
/// @dev Some stories can destroy items
function destroy(uint tokenId) external override {
IController c = IController(controller());
require(IChamberController(c.chamberController()).validChambers(msg.sender)
|| c.storyController() == msg.sender
|| ownerOf(tokenId) == msg.sender
, 'forbidden');
require(!equipped[tokenId], "equipped");
_destroy(tokenId);
}
function _destroy(uint tokenId) internal {
_burn(tokenId);
emit Destroyed(tokenId);
}
function _afterMint(uint tokenId) internal virtual {}
function _additionalAugment(uint tokenId) internal virtual {}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "../openzeppelin/ERC721EnumerableUpgradeable.sol";
import "../proxy/Controllable.sol";
abstract contract NftBase is ERC721EnumerableUpgradeable, Controllable {
// ---- CONSTANTS ----
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant NFT_BASE_VERSION = "1.0.1";
// ---- VARIABLES ----
uint internal idCounter = 1;
string internal __baseUri;
mapping(uint => string) internal _uniqueUri;
/// @dev This empty reserved space is put in place to allow future versions to add new
/// variables without shifting down storage in the inheritance chain.
/// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
uint256[47] private __gap;
// ---- EVENTS ----
event UniqueUriChanged(uint id, string uri);
event BaseUriChanged(string uri);
// ---- INITIALIZER ----
function __NftBase_init(
string memory name_,
string memory symbol_,
address controller_,
string memory uri
) internal {
_onlyInitializing();
__ERC721_init(name_, symbol_);
__Controllable_init(controller_);
idCounter = 1;
__baseUri = uri;
emit BaseUriChanged(uri);
}
function _incrementAndGetId() internal returns (uint){
uint id = idCounter;
idCounter = id + 1;
return id;
}
function onlyDeployer() internal view {
require(IController(controller()).isDeployer(msg.sender), "!deployer");
}
// ---- VIEWS ----
function _baseURI() internal view override returns (string memory) {
return __baseUri;
}
function exists(uint tokenId) external view returns (bool) {
return _exists(tokenId);
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(tokenId <= idCounter, "!exist");
// unique uri used for concrete tokenId
string memory uniqueURI = _uniqueUri[tokenId];
if (bytes(uniqueURI).length != 0) {
return uniqueURI;
}
// specific token uri used for group of ids based on nft internal logic (such as item rarity)
string memory specificURI = _specificURI(tokenId);
if (bytes(specificURI).length > 0) {
return specificURI;
}
return _baseURI();
}
function _specificURI(uint) internal view virtual returns (string memory) {
return "";
}
function baseURI() external view returns (string memory) {
return _baseURI();
}
// ---- GOV ACTIONS ----
function setUniqueUri(uint tokenId, string memory uri) external {
onlyDeployer();
_uniqueUri[tokenId] = uri;
emit UniqueUriChanged(tokenId, uri);
}
function setBaseUri(string memory value) external {
onlyDeployer();
__baseUri = value;
emit BaseUriChanged(value);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IStatController.sol";
interface IAttackItem {
struct GenerateAttackInfo {
IStatController.MagicAttackType attackType;
IStatController.CoreAttributes attributeFactors;
uint damageMin;
uint damageMax;
uint manaConsumeMin;
uint manaConsumeMax;
}
function attackAttributes(uint tokenId) external view returns (IStatController.MagicAttack memory);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IStatController.sol";
interface IBuffItem {
function buff(uint tokenId)
external view returns (uint[] memory casterBuff, uint[] memory casterDebuff, uint mana);
function debuff(uint tokenId)
external view returns (uint[] memory targetDebuff, uint[] memory targetBuff);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
interface IChamberController {
enum ChamberType {
UNKNOWN_0, // 0
ENEMY_NPC_1, // 1
ENEMY_NPC_SUPER_RARE_2, // 2
BOSS_3, // 3
SHRINE_4, // 4
CHEST_5, // 5
STORY_6, // 6
STORY_UNIQUE_7, // 7
SHRINE_UNIQUE_8, // 8
CHEST_UNIQUE_9, // 9
ENEMY_NPC_UNIQUE_10, // 10
STORY_ON_ROAD_11, // 11
STORY_UNDERGROUND_12, // 12
STORY_NIGHT_CAMP_13, // 13
STORY_MOUNTAIN_14, // 14
STORY_WATER_15, // 15
STORY_CASTLE_16, // 16
STORY_HELL_17, // 17
STORY_SPACE_18, // 18
STORY_WOOD_19, // 19
STORY_CATACOMBS_20, // 20
STORY_BAD_HOUSE_21, // 21
STORY_GOOD_TOWN_22, // 22
STORY_BAD_TOWN_23, // 23
STORY_BANDIT_CAMP_24, // 24
STORY_BEAST_LAIR_25, // 25
STORY_PRISON_26, // 26
STORY_SWAMP_27, // 27
STORY_INSIDE_28, // 28
STORY_OUTSIDE_29, // 29
STORY_INSIDE_RARE_30,
STORY_OUTSIDE_RARE_31,
ENEMY_NPC_INSIDE_32,
ENEMY_NPC_INSIDE_RARE_33,
ENEMY_NPC_OUTSIDE_34,
ENEMY_NPC_OUTSIDE_RARE_35,
SLOT_36,
SLOT_37,
SLOT_38,
SLOT_39,
SLOT_40,
SLOT_41,
SLOT_42,
SLOT_43,
SLOT_44,
SLOT_45,
SLOT_46,
SLOT_47,
SLOT_48,
SLOT_49,
SLOT_50
}
function validChambers(address chamber) external view returns (bool);
function chambersByTypeAndBiomeLevel(uint cType, uint biome, uint index) external view returns (address);
function chambersByTypeAndBiomeLevelLength(uint cType, uint biome) external view returns (uint);
function getRandomChamber(uint[] memory cTypes, uint[] memory chances, uint biomeLevel, address heroToken, uint heroTokenId) external returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IStatController.sol";
interface IConsumableItem {
struct GenerateConsumableInfo {
uint[] ids;
uint[] values;
bool[] increase;
}
function consumableAttributesAndStats(uint tokenId)
external view returns (uint[] memory positive, uint[] memory negative, IStatController.ChangeableStats memory stats);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
interface IControllable {
function VERSION() external pure returns (string memory);
function revision() external view returns (uint);
function previousImplementation() external view returns (address);
function isController(address _contract) external view returns (bool);
function isGovernance(address _contract) external view returns (bool);
function created() external view returns (uint256);
function createdBlock() external view returns (uint256);
function controller() external view returns (address);
function increaseRevision(address oldLogic) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
interface IController {
function dungeonSpecific(uint heroLvl, uint heroCls) external view returns (address);
function governance() external view returns (address);
function statController() external view returns (address);
function storyController() external view returns (address);
function chamberController() external view returns (address);
function reinforcementController() external view returns (address);
function oracle() external view returns (address);
function treasury() external view returns (address);
function fightCalculator() external view returns (address);
function itemCalculator() external view returns (address);
function dungeonFactory() external view returns (address);
function gameToken() external view returns (address);
function fightDelay() external view returns (uint);
function dungeonMultiplier(address dungeonImpl, address monsterProxy) external view returns (uint);
function validHeroes(address hero) external view returns (bool);
function validDungeons(address dungeon) external view returns (bool);
function validItems(address item) external view returns (bool);
function validTreasuryTokens(address token) external view returns (bool);
function heroes(uint id) external view returns (address);
function heroNameExist(string memory name) external view returns (bool);
function globalBiomeMonsterMultiplier(uint biome) external view returns (uint);
function dungeons(uint id) external view returns (address);
function items(uint id) external view returns (address);
function heroesLength() external view returns (uint);
function dungeonsLength() external view returns (uint);
function itemsLength() external view returns (uint);
function dungeonImplByBiomeLevel(uint level, uint index) external view returns (address);
function dungeonImplLength(uint level) external view returns (uint);
function minLevelForTreasury(address token) external view returns (uint);
function registerDungeon(address dungeonProxy) external;
function registerHeroName(string memory name) external;
function isDeployer(address adr) external view returns (bool);
function onPause() external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "../openzeppelin/IERC20.sol";
interface IGameToken is IERC20 {
function minter() external view returns (address);
function mint(address account, uint amount) external returns (bool);
function burn(uint amount) external returns (bool);
function setMinter(address _minter) external;
function pause(bool value) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IStatController.sol";
interface IHero {
struct TokenTreasury {
address token;
uint amount;
}
function attributes(uint tokenId) external view returns (uint[] memory);
function lastFightTs(uint tokenId) external view returns (uint);
function heroBiome(uint tokenId) external view returns (uint);
function stats(uint tokenId) external view returns (IStatController.ChangeableStats memory);
function currentDungeon(uint tokenId) external view returns (address);
function isOwner(address account, uint256 tokenId) external view returns (bool);
function isHero() external view returns (bool);
function payToken() external view returns (address);
function payTokenAmount() external view returns (uint);
function heroClass() external view returns (uint);
function score(uint tokenId) external view returns (uint);
function heroReinforcementHelp(uint tokenId) external view returns (address heroToken, uint heroId);
function isReadyToFight(uint tokenId) external view returns (bool);
function isAlive(uint tokenId) external view returns (bool);
function create(string memory name) external returns (uint);
function kill(uint heroId) external returns (IStatController.NftItem[] memory dropItems, uint dropTokenAmount);
function levelUp(uint tokenId, IStatController.CoreAttributes memory change) external;
function reduceDurability(uint heroId, uint dungeonLevel) external;
function changeCurrentDungeon(uint tokenId, address dungeon) external;
function refreshLastFight(uint tokenId) external;
function changeCurrentStats(
uint tokenId,
IStatController.ChangeableStats memory change,
bool increase
) external;
function tokenTreasures(uint tokenId) external view returns (uint);
function releaseReinforcement(uint heroId) external returns (address helperToken, uint helperId);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IStatController.sol";
interface IItem {
struct GenerateInfo {
uint[] ids;
uint[] mins;
uint[] maxs;
uint[] chances;
// it doesn't include positions with 100% chance
uint minRandomAttributes;
uint maxRandomAttributes;
}
enum FeeType {
UNKNOWN,
REPAIR,
AUGMENT
}
enum ItemRarity {
UNKNOWN, // 0
NORMAL, // 1
MAGIC, // 2
RARE, // 3
SET, // 4
UNIQUE // 5
}
enum ItemType {
NO_SLOT, // 0
HEAD, // 1
BODY, // 2
GLOVES, // 3
BELT, // 4
AMULET, // 5
RING, // 6
OFF_HAND, // 7
BOOTS, // 8
ONE_HAND, // 9
TWO_HAND, // 10
SKILL // 11
}
enum ItemMetaType {
UNKNOWN, // 0
COMMON, // 1
ATTACK_ITEM, // 2
BUFF_ITEM, // 3
CONSUMABLE_ITEM // 4
}
struct ItemMeta {
string name;
string symbol;
string uri;
address augmentToken;
uint augmentTokenAmount;
// Level in range 1-99. Reducing durability in low level dungeons. lvl/5+1 = biome
uint itemLevel;
ItemType itemType;
uint baseDurability;
}
function itemMetaType() external view returns (ItemMetaType);
function isOwner(address account, uint256 tokenId) external view returns (bool);
function augmentationLevel(uint tokenId) external view returns (uint);
function itemRarity(uint tokenId) external view returns (uint);
function baseDurability() external view returns (uint);
function itemDurability(uint tokenId) external view returns (uint);
function equipped(uint tokenId) external view returns (bool);
function equippedOn(uint tokenId, address heroAdr) external view returns (uint heroId);
function isItem() external pure returns (bool);
function isAttackItem() external view returns (bool);
function isBuffItem() external view returns (bool);
function isConsumableItem() external pure returns (bool);
function augmentToken() external returns (address);
function augmentTokenAmount() external returns (uint);
function itemLevel() external returns (uint);
function itemType() external returns (uint);
function itemAttributes(uint tokenId) external view returns (uint[] memory);
function negativeItemAttributes(uint tokenId) external view returns (uint[] memory);
function requirementAttributes() external returns (IStatController.CoreAttributes memory);
function score(uint tokenId) external view returns (uint);
function mint() external returns (uint tokenId);
function equip(uint tokenId, address heroToken, uint heroTokenId, uint itemSlot) external;
function takeOff(uint tokenId, address heroToken, uint heroTokenId, uint itemSlot, address destination, bool broken) external;
function reduceDurability(uint tokenId, uint dungeonBiomeLevel) external returns (uint);
function repairDurability(uint tokenId, uint consumedItemId) external;
function destroy(uint tokenId) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IItem.sol";
import "./IBuffItem.sol";
import "./IAttackItem.sol";
import "./IStatController.sol";
import "./IConsumableItem.sol";
interface IItemCalculator {
function augmentGovFee() external view returns (uint);
function repairGovFee() external view returns (uint);
function score(uint[] memory attributes, uint baseDurability) external view returns (uint);
function calcReduceDurability(
uint dungeonBiomeLevel,
uint currentDurability,
uint _itemLevel,
uint _itemType
) external pure returns (uint);
function augmentSuccess(uint random) external view returns (bool);
function generateAttributes(IItem.GenerateInfo memory _info, uint rarity) external returns (uint[] memory ids, uint[] memory values, IItem.ItemRarity itemRarity);
function generateSkillAttributes(IItem.GenerateInfo memory _info, bool onlyPositiveChances)
external returns (uint[] memory ids, uint[] memory values);
function generateAttack(IAttackItem.GenerateAttackInfo memory _info) external returns (IStatController.MagicAttack memory);
function augmentAttribute(uint value) external view returns (uint);
function augmentMagicAttack(IStatController.MagicAttack memory current) external pure returns (IStatController.MagicAttack memory);
function consumableInfoToGenerateInfo(IConsumableItem.GenerateConsumableInfo memory consumableGenInfo) external pure returns (IItem.GenerateInfo memory pos, IItem.GenerateInfo memory neg);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
interface IOracle {
function getRandomNumber(uint max, uint seed) external returns (uint);
function getRandomNumberInRange(uint min, uint max, uint seed) external returns (uint);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IStatController.sol";
interface IReinforcementController {
function toHelperRatio(address heroToken, uint heroId) external view returns (uint);
function isStaked(address heroToken, uint heroId) external view returns (bool);
function askHero(uint biome) external returns (address heroToken, uint heroId, uint[] memory attributes);
function registerTokenReward(address heroToken, uint heroId, address token, uint amount) external;
function registerNftReward(address heroToken, uint heroId, address token, uint tokenId) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
interface IStatController {
enum ATTRIBUTES {
// core
STRENGTH, // 0
DEXTERITY, // 1
VITALITY, // 2
ENERGY, // 3
// attributes
DAMAGE_MIN, // 4
DAMAGE_MAX, // 5
ATTACK_RATING, // 6
DEFENSE, // 7
BLOCK_RATING, // 8
LIFE, // 9
MANA, // 10
// resistance
FIRE_RESISTANCE, // 11
COLD_RESISTANCE, // 12
LIGHTNING_RESISTANCE, // 13
// dmg against
DMG_AGAINST_HUMAN, // 14
DMG_AGAINST_UNDEAD, // 15
DMG_AGAINST_DAEMON, // 16
DMG_AGAINST_BEAST, // 17
// defence against
DEF_AGAINST_HUMAN, // 18
DEF_AGAINST_UNDEAD, // 19
DEF_AGAINST_DAEMON, // 20
DEF_AGAINST_BEAST, // 21
// --- unique, not augmentable
// hero will not die until have positive chances
LIFE_CHANCES, // 22
// increase chance to get an item
MAGIC_FIND, // 23
// decrease chance to get an item
DESTROY_ITEMS, // 24
// percent of chance x2 dmg
CRITICAL_HIT, // 25
// dmg factors
MELEE_DMG_FACTOR, // 26
FIRE_DMG_FACTOR, // 27
COLD_DMG_FACTOR, // 28
LIGHTNING_DMG_FACTOR, // 29
// increase attack rating on given percent
AR_FACTOR, // 30
// percent of damage will be converted to HP
LIFE_STOLEN_PER_HIT, // 31
// amount of mana restored after each battle
MANA_AFTER_KILL, // 32
// reduce all damage on percent after all other reductions
DAMAGE_REDUCTION, // 33
// -- statuses
// chance to stun an enemy, stunned enemy skip next hit
STUN, // 34
// chance burn an enemy, burned enemy will loss 50% of defence
BURN, // 35
// chance freeze an enemy, frozen enemy will loss 50% of MELEE damage
FREEZE, // 36
// chance to reduce enemy's attack rating on 50%
CONFUSE, // 37
// chance curse an enemy, cursed enemy will loss 50% of resistance
CURSE, // 38
// percent of dmg return to attacker
REFLECT_DAMAGE_MELEE, // 39
REFLECT_DAMAGE_MAGIC, // 40
// chance to poison enemy, poisoned enemy will loss 10% of the current health
POISON, // 41
// reduce chance get any of uniq statuses
RESIST_TO_STATUSES, // 42
END_SLOT // 46
}
// possible
// HEAL_FACTOR
struct CoreAttributes {
uint strength;
uint dexterity;
uint vitality;
uint energy;
}
struct ChangeableStats {
uint level;
uint experience;
uint life;
uint mana;
uint lifeChances;
}
enum MagicAttackType {
UNKNOWN, // 0
FIRE, // 1
COLD, // 2
LIGHTNING, // 3
CHAOS // 4
}
struct MagicAttack {
MagicAttackType aType;
uint min;
uint max;
// if not zero - activate attribute factor for the attribute
CoreAttributes attributeFactors;
uint manaConsume;
}
enum ItemSlots {
UNKNOWN, // 0
HEAD, // 1
BODY, // 2
GLOVES, // 3
BELT, // 4
AMULET, // 5
BOOTS, // 6
RIGHT_RING, // 7
LEFT_RING, // 8
RIGHT_HAND, // 9
LEFT_HAND, // 10
TWO_HAND, // 11
SKILL_1, // 12
SKILL_2, // 13
SKILL_3, // 14
END_SLOT // 15
}
struct NftItem {
address token;
uint tokenId;
}
enum Race {
UNKNOWN, // 0
HUMAN, // 1
UNDEAD, // 2
DAEMON, // 3
BEAST, // 4
SLOT_5, // 5
SLOT_6, // 6
SLOT_7, // 7
SLOT_8, // 8
SLOT_9, // 9
SLOT_10 // 10
}
struct ChangeAttributesInfo {
address heroToken;
uint heroTokenId;
uint[] changeAttributes;
bool increase;
bool temporally;
}
struct BuffInfo {
address heroToken;
uint heroTokenId;
uint heroLevel;
address[] buffTokens;
uint[] buffTokenIds;
}
function initNewHero(address token, uint tokenId, uint heroClass) external;
function heroAttributes(address token, uint tokenId) external view returns (uint[] memory);
function heroAttribute(address token, uint tokenId, uint index) external view returns (uint);
function heroAttributesLength(address token, uint tokenId) external view returns (uint);
function heroBaseAttributes(address token, uint tokenId) external view returns (CoreAttributes memory);
function heroCustomData(address token, uint tokenId, bytes32 index) external view returns (uint);
function globalCustomData(bytes32 index) external view returns (uint);
function heroStats(address token, uint tokenId) external view returns (ChangeableStats memory);
function heroItemSlot(address token, uint tokenId, uint itemSlot) external view returns (NftItem memory);
function heroItemSlots(address heroToken, uint heroTokenId) external view returns (uint[] memory);
function isHeroAlive(address heroToken, uint heroTokenId) external view returns (bool);
function levelUp(address token, uint tokenId, uint heroClass, CoreAttributes memory change) external;
function changeHeroItemSlot(
address heroToken,
uint heroTokenId,
uint itemType,
uint itemSlot,
address itemToken,
uint itemTokenId,
bool equip
) external;
function changeCurrentStats(
address token,
uint tokenId,
ChangeableStats memory change,
bool increase
) external;
function changeBonusAttributes(ChangeAttributesInfo memory info) external;
function registerConsumableUsage(address heroToken, uint heroTokenId, address item) external;
function clearUsedConsumables(address heroToken, uint heroTokenId) external;
function clearTemporallyAttributes(address heroToken, uint heroTokenId) external;
function buffHero(BuffInfo memory info) external view returns (uint[] memory attributes, uint manaConsumed);
function generateMonsterAttributes(
uint[] memory ids,
uint[] memory values,
uint amplifier,
uint dungeonMultiplier,
uint baseExperience
) external pure returns (uint[] memory attributes, uint experience);
function setHeroCustomData(address token, uint tokenId, bytes32 index, uint value) external;
function setGlobalCustomData(bytes32 index, uint value) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./IItem.sol";
interface ITreasury {
function balanceOfToken(address token) external view returns (uint);
function sendToDungeon(address dungeon, address token, uint amount) external;
function sendFee(address token, uint amount, IItem.FeeType feeType) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
library CalcLib {
function toUint(int n) internal pure returns (uint) {
if (n < 0) {
return 0;
}
return uint(n);
}
/// @dev Simplified pseudo-random for minor functionality
function pseudoRandom(uint maxValue) internal view returns (uint) {
if (maxValue == 0) {
return 0;
}
// pseudo random number
return (uint(keccak256(abi.encodePacked(blockhash(block.number), block.coinbase, block.difficulty, block.number, block.timestamp, tx.gasprice, gasleft()))) % (maxValue + 1));
}
/// @dev Simplified pseudo-random for minor functionality
function pseudoRandomWithSeed(uint maxValue, uint seed) internal view returns (uint) {
if (maxValue == 0) {
return 0;
}
// pseudo random number
return (uint(keccak256(abi.encodePacked(blockhash(block.number), block.coinbase, block.difficulty, block.number, block.timestamp, tx.gasprice, gasleft(), seed))) % (maxValue + 1));
}
/// @dev Simplified pseudo-random for minor functionality, in range
function pseudoRandomInRange(uint min, uint max) internal view returns (uint) {
if (min >= max) {
return max;
}
uint r = pseudoRandom(max - min);
return min + r;
}
function minusWithZeroFloor(uint a, uint b) internal pure returns (uint){
if (a <= b) {
return 0;
}
return a - b;
}
function sqrt(uint x) internal pure returns (uint z) {
assembly {
// Start off with z at 1.
z := 1
// Used below to help find a nearby power of 2.
let y := x
// Find the lowest power of 2 that is at least sqrt(x).
if iszero(lt(y, 0x100000000000000000000000000000000)) {
y := shr(128, y) // Like dividing by 2 ** 128.
z := shl(64, z) // Like multiplying by 2 ** 64.
}
if iszero(lt(y, 0x10000000000000000)) {
y := shr(64, y) // Like dividing by 2 ** 64.
z := shl(32, z) // Like multiplying by 2 ** 32.
}
if iszero(lt(y, 0x100000000)) {
y := shr(32, y) // Like dividing by 2 ** 32.
z := shl(16, z) // Like multiplying by 2 ** 16.
}
if iszero(lt(y, 0x10000)) {
y := shr(16, y) // Like dividing by 2 ** 16.
z := shl(8, z) // Like multiplying by 2 ** 8.
}
if iszero(lt(y, 0x100)) {
y := shr(8, y) // Like dividing by 2 ** 8.
z := shl(4, z) // Like multiplying by 2 ** 4.
}
if iszero(lt(y, 0x10)) {
y := shr(4, y) // Like dividing by 2 ** 4.
z := shl(2, z) // Like multiplying by 2 ** 2.
}
if iszero(lt(y, 0x8)) {
// Equivalent to 2 ** z.
z := shl(1, z)
}
// Shifting right by 1 is like dividing by 2.
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
// Compute a rounded down version of z.
let zRoundDown := div(x, z)
// If zRoundDown is smaller, use it.
if lt(zRoundDown, z) {
z := zRoundDown
}
}
}
/*********************************************
* PRB-MATH *
* https://github.com/hifi-finance/prb-math *
**********************************************/
/// @notice Calculates the binary logarithm of x.
///
/// @dev Based on the iterative approximation algorithm.
/// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
///
/// Requirements:
/// - x must be greater than or equal to SCALE, otherwise the result would be negative.
///
/// Caveats:
/// - The results are nor perfectly accurate to the last decimal,
/// due to the lossy precision of the iterative approximation.
///
/// @param x The unsigned 60.18-decimal fixed-point number for which
/// to calculate the binary logarithm.
/// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.
function log2(uint256 x) internal pure returns (uint256 result) {
require(x >= 1e18, "x too low");
// Calculate the integer part of the logarithm
// and add it to the result and finally calculate y = x * 2^(-n).
uint256 n = mostSignificantBit(x / 1e18);
// The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number.
// The operation can't overflow because n is maximum 255 and SCALE is 1e18.
uint256 rValue = n * 1e18;
// This is y = x * 2^(-n).
uint256 y = x >> n;
// If y = 1, the fractional part is zero.
if (y == 1e18) {
return rValue;
}
// Calculate the fractional part via the iterative approximation.
// The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster.
for (uint256 delta = 5e17; delta > 0; delta >>= 1) {
y = (y * y) / 1e18;
// Is y^2 > 2 and so in the range [2,4)?
if (y >= 2 * 1e18) {
// Add the 2^(-m) factor to the logarithm.
rValue += delta;
// Corresponds to z/2 on Wikipedia.
y >>= 1;
}
}
return rValue;
}
/// @notice Finds the zero-based index of the first one in the binary representation of x.
/// @dev See the note on msb in the "Find First Set"
/// Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
/// @param x The uint256 number for which to find the index of the most significant bit.
/// @return msb The index of the most significant bit as an uint256.
//noinspection NoReturn
function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
if (x >= 2 ** 128) {
x >>= 128;
msb += 128;
}
if (x >= 2 ** 64) {
x >>= 64;
msb += 64;
}
if (x >= 2 ** 32) {
x >>= 32;
msb += 32;
}
if (x >= 2 ** 16) {
x >>= 16;
msb += 16;
}
if (x >= 2 ** 8) {
x >>= 8;
msb += 8;
}
if (x >= 2 ** 4) {
x >>= 4;
msb += 4;
}
if (x >= 2 ** 2) {
x >>= 2;
msb += 2;
}
if (x >= 2 ** 1) {
// No need to shift x any more.
msb += 1;
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "./StructLib.sol";
import "../interfaces/IItemCalculator.sol";
import "../interfaces/IController.sol";
import "../interfaces/IReinforcementController.sol";
import "../interfaces/IHero.sol";
import "../interfaces/ITreasury.sol";
import "../interfaces/IOracle.sol";
import "../openzeppelin/SafeERC20.sol";
library ItemLib {
using SafeERC20 for IERC20;
using EnumerableMap for EnumerableMap.UintToIntMap;
using StructLib for EnumerableMap.UintToIntMap;
function generateAttributes(
IItemCalculator itemCalculator,
EnumerableMap.UintToIntMap storage attributes,
IItem.GenerateInfo memory info,
uint _defaultRarity
) external returns (uint) {
(uint[] memory ids, uint[] memory values, IItem.ItemRarity rarity) = itemCalculator.generateAttributes(info, _defaultRarity);
for (uint i; i < values.length;) {
uint value = values[i];
uint index = ids[i];
if (value != 0) {
attributes.setUint(index, value);
}
unchecked{++i;}
}
return uint(rarity);
}
struct EquipContext {
address sender;
IController _controller;
uint tokenId;
address heroToken;
uint heroTokenId;
uint itemSlot;
uint _itemType;
uint _baseDurability;
uint _itemDurability;
IStatController.CoreAttributes requirements;
}
function equip(
mapping(uint => EnumerableMap.UintToIntMap) storage _itemAttributes,
mapping(uint => EnumerableMap.UintToIntMap) storage _negativeItemAttributes,
EquipContext memory context
) external {
require(IHero(context.heroToken).isOwner(context.sender, context.heroTokenId), "!owner");
require(context._controller.validHeroes(context.heroToken), "forbidden");
require(IHero(context.heroToken).currentDungeon(context.heroTokenId) == address(0), "in dungeon");
require(!IReinforcementController(context._controller.reinforcementController()).isStaked(context.heroToken, context.heroTokenId), "staked");
IStatController _statController = IStatController(context._controller.statController());
_checkRequirements(_statController, context.heroToken, context.heroTokenId, context.requirements);
require(context._itemType != 0, "consumable");
require(context._baseDurability == 0 || context._itemDurability > 0, "broken");
_statController.changeHeroItemSlot(
context.heroToken,
context.heroTokenId,
context._itemType,
context.itemSlot,
address(this),
context.tokenId,
true
);
if (_itemAttributes[context.tokenId].length() != 0) {
_statController.changeBonusAttributes(IStatController.ChangeAttributesInfo({
heroToken: context.heroToken,
heroTokenId: context.heroTokenId,
changeAttributes: _itemAttributes[context.tokenId].flat(),
increase: true,
temporally: false
}));
require(_statController.heroStats(context.heroToken, context.heroTokenId).life > 0, "!life");
}
if (_negativeItemAttributes[context.tokenId].length() != 0) {
_statController.changeBonusAttributes(IStatController.ChangeAttributesInfo({
heroToken: context.heroToken,
heroTokenId: context.heroTokenId,
changeAttributes: _negativeItemAttributes[context.tokenId].flat(),
increase: false,
temporally: false
}));
}
}
function augment(
address sender,
address token,
uint augmentTokenAmount,
uint tokenId,
uint consumedItemId,
uint ag,
IController _controller,
mapping(uint => bool) storage equipped,
mapping(uint => EnumerableMap.UintToIntMap) storage _itemAttributes
) external returns (bool success, uint agLevel){
require(token != address(0), "!augmentation");
require(!equipped[tokenId] && !equipped[consumedItemId], "equipped");
require(!_controller.onPause(), 'paused');
require(ag < 10, 'too high ag lvl');
IItemCalculator itemCalculator = IItemCalculator(_controller.itemCalculator());
sendFee(_controller, token, IItem.FeeType.AUGMENT, sender, augmentTokenAmount);
success = itemCalculator.augmentSuccess(IOracle(_controller.oracle()).getRandomNumber(1e18, 0));
if (!success) {
return (false, ag);
}
EnumerableMap.UintToIntMap storage attributes = _itemAttributes[tokenId];
uint length = attributes.length();
for (uint i; i < length;) {
(uint index, int valueI) = attributes._at(i);
if (valueI > 0) {
uint value = uint(valueI);
attributes.setUint(index, itemCalculator.augmentAttribute(value));
}
unchecked{++i;}
}
return (true, ag + 1);
}
function checkRequirements(IStatController _statController, address heroToken, uint heroTokenId, IStatController.CoreAttributes memory requirements) external view {
_checkRequirements(_statController, heroToken, heroTokenId, requirements);
}
function _checkRequirements(IStatController _statController, address heroToken, uint heroTokenId, IStatController.CoreAttributes memory requirements) internal view {
IStatController.CoreAttributes memory attributes = _statController.heroBaseAttributes(heroToken, heroTokenId);
require(requirements.strength <= attributes.strength
&& requirements.dexterity <= attributes.dexterity
&& requirements.vitality <= attributes.vitality
&& requirements.energy <= attributes.energy
, "!attributes");
}
function sendFee(IController _controller, address token, IItem.FeeType feeType, address sender, uint amount) public {
if (token != address(0)) {
address treasury = _controller.treasury();
IERC20(token).safeTransferFrom(
sender,
address(this),
amount
);
IERC20(token).safeApprove(treasury, amount);
ITreasury(treasury).sendFee(token, amount, feeType);
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Library for setting / getting slot variables (used in upgradable proxy contracts)
/// @author bogdoslav
library SlotsLib {
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant SLOT_LIB_VERSION = "1.0.0";
// ************* GETTERS *******************
/// @dev Gets a slot as bytes32
function getBytes32(bytes32 slot) internal view returns (bytes32 result) {
assembly {
result := sload(slot)
}
}
/// @dev Gets a slot as an address
function getAddress(bytes32 slot) internal view returns (address result) {
assembly {
result := sload(slot)
}
}
/// @dev Gets a slot as uint256
function getUint(bytes32 slot) internal view returns (uint result) {
assembly {
result := sload(slot)
}
}
// ************* ARRAY GETTERS *******************
/// @dev Gets an array length
function arrayLength(bytes32 slot) internal view returns (uint result) {
assembly {
result := sload(slot)
}
}
/// @dev Gets a slot array by index as address
/// @notice First slot is array length, elements ordered backward in memory
/// @notice This is unsafe, without checking array length.
function addressAt(bytes32 slot, uint index) internal view returns (address result) {
bytes32 pointer = bytes32(uint(slot) - 1 - index);
assembly {
result := sload(pointer)
}
}
// ************* SETTERS *******************
/// @dev Sets a slot with bytes32
/// @notice Check address for 0 at the setter
function set(bytes32 slot, bytes32 value) internal {
assembly {
sstore(slot, value)
}
}
/// @dev Sets a slot with address
/// @notice Check address for 0 at the setter
function set(bytes32 slot, address value) internal {
assembly {
sstore(slot, value)
}
}
/// @dev Sets a slot with uint
function set(bytes32 slot, uint value) internal {
assembly {
sstore(slot, value)
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "../interfaces/IStatController.sol";
import "../interfaces/IHero.sol";
import "../openzeppelin/Math.sol";
import "./CalcLib.sol";
import "../openzeppelin/EnumerableMap.sol";
import "./StructLib.sol";
library StatLib {
using StructLib for EnumerableMap.UintToIntMap;
using EnumerableMap for EnumerableMap.UintToIntMap;
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant STAT_LIB_VERSION = "1.0.0";
uint public constant MAX_LEVEL = 99;
uint public constant BASE_EXPERIENCE = 100_000;
uint public constant BIOME_LEVEL_STEP = 5;
uint internal constant _MAX_AMPLIFIER = 1e18;
struct BaseMultiplier {
uint minDamage;
uint maxDamage;
uint attackRating;
uint defense;
uint blockRating;
uint life;
uint mana;
}
struct LevelUp {
uint life;
uint mana;
}
struct InitialHero {
IStatController.CoreAttributes core;
BaseMultiplier multiplier;
LevelUp levelUp;
uint baseLifeChances;
}
uint private constant _PRECISION = 1e18;
// --------- BASE -----------
// --- HERO 1 (Slave) ---
function initialHero1() internal pure returns (InitialHero memory) {
return InitialHero({
core: IStatController.CoreAttributes({
strength: 15,
dexterity: 15,
vitality: 30,
energy: 10
}),
multiplier: BaseMultiplier({
minDamage: 0.1e18,
maxDamage: 0.2e18,
attackRating: 2e18,
defense: 2e18,
blockRating: 0.1e18,
life: 1.5e18,
mana: 0.5e18
}),
levelUp: LevelUp({
life: 2e18,
mana: 1e18
}),
baseLifeChances: 5
});
}
// --- HERO 2 (Spata) ---
function initialHero2() internal pure returns (InitialHero memory) {
return InitialHero({
core: IStatController.CoreAttributes({
strength: 30,
dexterity: 5,
vitality: 25,
energy: 10
}),
multiplier: BaseMultiplier({
minDamage: 0.15e18,
maxDamage: 0.25e18,
attackRating: 2e18,
defense: 1e18,
blockRating: 0.08e18,
life: 1.3e18,
mana: 0.5e18
}),
levelUp: LevelUp({
life: 1.8e18,
mana: 1e18
}),
baseLifeChances: 5
});
}
// --- HERO 3 (Decidia) ---
function initialHero3() internal pure returns (InitialHero memory) {
return InitialHero({
core: IStatController.CoreAttributes({
strength: 10,
dexterity: 15,
vitality: 20,
energy: 25
}),
multiplier: BaseMultiplier({
minDamage: 0.1e18,
maxDamage: 0.2e18,
attackRating: 2e18,
defense: 1e18,
blockRating: 0.1e18,
life: 1e18,
mana: 2e18
}),
levelUp: LevelUp({
life: 1.3e18,
mana: 2e18
}),
baseLifeChances: 5
});
}
// --- HERO 4 (Innatus) ---
function initialHero4() internal pure returns (InitialHero memory) {
return InitialHero({
core: IStatController.CoreAttributes({
strength: 15,
dexterity: 25,
vitality: 15,
energy: 15
}),
multiplier: BaseMultiplier({
minDamage: 0.1e18,
maxDamage: 0.2e18,
attackRating: 4e18,
defense: 3e18,
blockRating: 0.2e18,
life: 1.2e18,
mana: 1e18
}),
levelUp: LevelUp({
life: 1.7e18,
mana: 1.5e18
}),
baseLifeChances: 5
});
}
// --- HERO 5 (F2P) ---
function initialHero5() internal pure returns (InitialHero memory) {
return InitialHero({
core: IStatController.CoreAttributes({
strength: 20,
dexterity: 20,
vitality: 20,
energy: 10
}),
multiplier: BaseMultiplier({
minDamage: 0.15e18,
maxDamage: 0.25e18,
attackRating: 3e18,
defense: 2.5e18,
blockRating: 0.15e18,
life: 1.5e18,
mana: 1.5e18
}),
levelUp: LevelUp({
life: 1.5e18,
mana: 1.5e18
}),
baseLifeChances: 1
});
}
// ------
function initialHero(uint heroClass) internal pure returns (InitialHero memory) {
if (heroClass == 1) {
return initialHero1();
} else if (heroClass == 2) {
return initialHero2();
} else if (heroClass == 3) {
return initialHero3();
} else if (heroClass == 4) {
return initialHero4();
} else if (heroClass == 5) {
return initialHero5();
} else {
revert("Unknown class");
}
}
// --------- CALCULATIONS -----------
function minDamage(uint strength, uint heroClass) internal pure returns (uint){
return strength * initialHero(heroClass).multiplier.minDamage / _PRECISION;
}
function maxDamage(uint strength, uint heroClass) internal pure returns (uint){
return strength * initialHero(heroClass).multiplier.maxDamage / _PRECISION;
}
function attackRating(uint dexterity, uint heroClass) internal pure returns (uint){
return dexterity * initialHero(heroClass).multiplier.attackRating / _PRECISION;
}
function defense(uint dexterity, uint heroClass) internal pure returns (uint){
return dexterity * initialHero(heroClass).multiplier.defense / _PRECISION;
}
function blockRating(uint dexterity, uint heroClass) internal pure returns (uint){
return Math.min((dexterity * initialHero(heroClass).multiplier.blockRating / _PRECISION), 75);
}
function life(uint vitality, uint heroClass, uint level) internal pure returns (uint){
return (vitality * initialHero(heroClass).multiplier.life / _PRECISION)
+ (level * initialHero(heroClass).levelUp.life / _PRECISION);
}
function mana(uint energy, uint heroClass, uint level) internal pure returns (uint){
return (energy * initialHero(heroClass).multiplier.mana / _PRECISION)
+ (level * initialHero(heroClass).levelUp.mana / _PRECISION);
}
function lifeChances(uint heroClass, uint level) internal pure returns (uint){
return initialHero(heroClass).baseLifeChances + (level / 49);
}
function levelExperience(uint level) internal pure returns (uint) {
if (level == 0 || level >= MAX_LEVEL) {
return 0;
}
return level * BASE_EXPERIENCE * (67e17 - CalcLib.log2((MAX_LEVEL - level + 2) * 1e18)) / 1e18;
}
function chanceToHit(
uint attackersAttackRating,
uint defendersDefenceRating,
uint attackersLevel,
uint defendersLevel,
uint arFactor
) internal pure returns (uint) {
attackersAttackRating += attackersAttackRating * arFactor / 100;
uint x = Math.max(attackersAttackRating, 1);
uint y = Math.max(attackersAttackRating + defendersDefenceRating, 1);
uint z = attackersLevel;
uint k = defendersLevel / 2;
uint xy = x * 1e18 / y;
uint zk = z * 1e18 / (attackersLevel + k);
uint base = 2 * xy * zk / 1e18;
return Math.max(Math.min(base, 0.95e18), 0.05e18);
}
function experienceToLvl(uint experience, uint startFromLevel) internal pure returns (uint level) {
level = startFromLevel;
for (; level < MAX_LEVEL;) {
if (levelExperience(level) >= experience) {
break;
}
unchecked{++level;}
}
}
function expPerMonster(uint monsterExp, uint monsterRarity, uint heroExp, uint heroCurrentLvl, uint monsterBiome) internal pure returns (uint) {
uint heroLvl = experienceToLvl(heroExp, heroCurrentLvl);
uint heroBiome = heroLvl / StatLib.BIOME_LEVEL_STEP + 1;
uint base = monsterExp + monsterExp * monsterRarity / _MAX_AMPLIFIER;
// reduce exp if hero not in his biome
if (heroBiome > monsterBiome) {
base = base / (2 ** (heroBiome - monsterBiome));
}
return base;
}
function amplify(uint value, uint amplifier, uint dungeonMultiplier) internal pure returns (uint) {
if (value == 0) {
return 0;
}
return value + (value * amplifier / _MAX_AMPLIFIER) + (value * dungeonMultiplier / _MAX_AMPLIFIER);
}
function mintDropChance(uint baseChance, uint monsterRarity, uint monsterBiome, uint heroExp, uint heroCurrentLvl) internal pure returns (uint) {
uint heroLvl = StatLib.experienceToLvl(heroExp, heroCurrentLvl);
uint heroBiome = heroLvl / StatLib.BIOME_LEVEL_STEP + 1;
uint chance = baseChance + baseChance * monsterRarity / _MAX_AMPLIFIER;
// reduce chance if hero not in his biome
if (heroBiome > monsterBiome) {
chance = chance / (2 ** (heroBiome - monsterBiome));
}
return chance;
}
function initAttributes(
EnumerableMap.UintToIntMap storage attributes,
uint heroClass,
uint level,
IStatController.CoreAttributes memory base
) internal {
attributes.setUint(uint(IStatController.ATTRIBUTES.STRENGTH), base.strength);
attributes.setUint(uint(IStatController.ATTRIBUTES.DEXTERITY), base.dexterity);
attributes.setUint(uint(IStatController.ATTRIBUTES.VITALITY), base.vitality);
attributes.setUint(uint(IStatController.ATTRIBUTES.ENERGY), base.energy);
attributes.setUint(uint(IStatController.ATTRIBUTES.DAMAGE_MIN), minDamage(base.strength, heroClass));
attributes.setUint(uint(IStatController.ATTRIBUTES.DAMAGE_MAX), maxDamage(base.strength, heroClass));
attributes.setUint(uint(IStatController.ATTRIBUTES.ATTACK_RATING), attackRating(base.dexterity, heroClass));
attributes.setUint(uint(IStatController.ATTRIBUTES.DEFENSE), defense(base.dexterity, heroClass));
attributes.setUint(uint(IStatController.ATTRIBUTES.BLOCK_RATING), blockRating(base.dexterity, heroClass));
attributes.setUint(uint(IStatController.ATTRIBUTES.LIFE), life(base.vitality, heroClass, level));
attributes.setUint(uint(IStatController.ATTRIBUTES.MANA), mana(base.energy, heroClass, level));
attributes.setUint(uint(IStatController.ATTRIBUTES.LIFE_CHANCES), lifeChances(heroClass, level));
}
function updateCoreDependAttributesInMemory(uint[] memory attributes, uint[] memory bonus, uint heroClass, uint level) internal pure returns (uint[] memory) {
uint strength = attributes[uint(IStatController.ATTRIBUTES.STRENGTH)];
uint dexterity = attributes[uint(IStatController.ATTRIBUTES.DEXTERITY)];
uint vitality = attributes[uint(IStatController.ATTRIBUTES.VITALITY)];
uint energy = attributes[uint(IStatController.ATTRIBUTES.ENERGY)];
attributes[uint(IStatController.ATTRIBUTES.DAMAGE_MIN)] = minDamage(strength, heroClass) + bonus[uint(IStatController.ATTRIBUTES.DAMAGE_MIN)];
attributes[uint(IStatController.ATTRIBUTES.DAMAGE_MAX)] = maxDamage(strength, heroClass) + bonus[uint(IStatController.ATTRIBUTES.DAMAGE_MAX)];
attributes[uint(IStatController.ATTRIBUTES.ATTACK_RATING)] = attackRating(dexterity, heroClass) + bonus[uint(IStatController.ATTRIBUTES.ATTACK_RATING)];
attributes[uint(IStatController.ATTRIBUTES.DEFENSE)] = defense(dexterity, heroClass) + bonus[uint(IStatController.ATTRIBUTES.DEFENSE)];
attributes[uint(IStatController.ATTRIBUTES.BLOCK_RATING)] = blockRating(dexterity, heroClass) + bonus[uint(IStatController.ATTRIBUTES.BLOCK_RATING)];
attributes[uint(IStatController.ATTRIBUTES.LIFE)] = life(vitality, heroClass, level) + bonus[uint(IStatController.ATTRIBUTES.LIFE)];
attributes[uint(IStatController.ATTRIBUTES.MANA)] = mana(energy, heroClass, level) + bonus[uint(IStatController.ATTRIBUTES.MANA)];
return attributes;
}
function updateCoreDependAttributes(
EnumerableMap.UintToIntMap storage attributes,
EnumerableMap.UintToIntMap storage bonusMain,
EnumerableMap.UintToIntMap storage bonusExtra,
IStatController.ChangeableStats storage _heroStats,
uint index,
address heroToken,
uint base
) internal {
if (index == uint(IStatController.ATTRIBUTES.STRENGTH)) {
uint heroClass = IHero(heroToken).heroClass();
attributes.setUint(uint(IStatController.ATTRIBUTES.DAMAGE_MIN),
StatLib.minDamage(base, heroClass)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.DAMAGE_MIN)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.DAMAGE_MIN)
);
attributes.setUint(uint(IStatController.ATTRIBUTES.DAMAGE_MAX),
StatLib.maxDamage(base, heroClass)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.DAMAGE_MAX)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.DAMAGE_MAX)
);
} else if (index == uint(IStatController.ATTRIBUTES.DEXTERITY)) {
uint heroClass = IHero(heroToken).heroClass();
attributes.setUint(uint(IStatController.ATTRIBUTES.ATTACK_RATING),
StatLib.attackRating(base, heroClass)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.ATTACK_RATING)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.ATTACK_RATING)
);
attributes.setUint(uint(IStatController.ATTRIBUTES.DEFENSE),
StatLib.defense(base, heroClass)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.DEFENSE)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.DEFENSE)
);
attributes.setUint(uint(IStatController.ATTRIBUTES.BLOCK_RATING),
StatLib.blockRating(base, heroClass)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.BLOCK_RATING)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.BLOCK_RATING)
);
} else if (index == uint(IStatController.ATTRIBUTES.VITALITY)) {
uint heroClass = IHero(heroToken).heroClass();
uint level = _heroStats.level;
attributes.setUint(uint(IStatController.ATTRIBUTES.LIFE),
StatLib.life(base, heroClass, level)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.LIFE)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.LIFE)
);
} else if (index == uint(IStatController.ATTRIBUTES.ENERGY)) {
uint heroClass = IHero(heroToken).heroClass();
uint level = _heroStats.level;
attributes.setUint(uint(IStatController.ATTRIBUTES.MANA),
StatLib.mana(base, heroClass, level)
+ bonusMain.getOrZeroA(IStatController.ATTRIBUTES.MANA)
+ bonusExtra.getOrZeroA(IStatController.ATTRIBUTES.MANA)
);
}
}
function attributesAdd(uint[] memory base, uint[] memory add) internal pure returns (uint[] memory) {
unchecked{
for (uint i; i < base.length; ++i) {
base[i] += add[i];
}
}
return base;
}
function attributesRemove(uint[] memory base, uint[] memory remove) internal pure returns (uint[] memory) {
unchecked{
for (uint i; i < base.length; ++i) {
base[i] = CalcLib.minusWithZeroFloor(base[i], remove[i]);
}
}
return base;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "../openzeppelin/EnumerableMap.sol";
import "../interfaces/IStatController.sol";
library StructLib {
using EnumerableMap for EnumerableMap.UintToIntMap;
function flat(EnumerableMap.UintToIntMap storage map) internal view returns (uint[] memory){
unchecked{
uint length = map.length();
uint[] memory values = new uint[](uint(IStatController.ATTRIBUTES.END_SLOT));
for (uint i; i < length; ++i) {
(uint index, int value) = map._at(i);
if (value < 0) {
value = 0;
}
values[index] = uint(value);
}
return values;
}
}
function flatInt(EnumerableMap.UintToIntMap storage map) internal view returns (int[] memory){
unchecked{
uint length = map.length();
int[] memory values = new int[](uint(IStatController.ATTRIBUTES.END_SLOT));
for (uint i; i < length; ++i) {
(uint index, int value) = map._at(i);
values[index] = value;
}
return values;
}
}
function getOrZeroA(EnumerableMap.UintToIntMap storage map, IStatController.ATTRIBUTES index) internal view returns (uint) {
(,int value) = map.tryGet(uint(index));
if (value < 0) {
value = 0;
}
return uint(value);
}
function getOrZero(EnumerableMap.UintToIntMap storage map, uint index) internal view returns (uint) {
(,int value) = map.tryGet(index);
if (value < 0) {
value = 0;
}
return uint(value);
}
function getOrZeroInt(EnumerableMap.UintToIntMap storage map, uint index) internal view returns (int) {
(,int value) = map.tryGet(index);
return value;
}
function increment(EnumerableMap.UintToIntMap storage map, uint index, uint value) internal returns (uint) {
(,int oldValue) = map.tryGet(index);
int newValue = oldValue + int(value);
map._set(index, newValue);
return uint(newValue);
}
function decrement(EnumerableMap.UintToIntMap storage map, uint index, int value) internal returns (int) {
(,int oldValue) = map.tryGet(index);
int newValue = oldValue - int(value);
if (newValue == 0) {
map.remove(index);
} else {
map._set(index, newValue);
}
return newValue;
}
}// 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
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableMap.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
pragma solidity ^0.8.0;
import "./EnumerableSet.sol";
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* The following map types are supported:
*
* - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
* - `address -> uint256` (`AddressToUintMap`) since v4.6.0
* - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0
* - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
* - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableMap.
* ====
*/
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct Bytes32ToBytes32Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
Bytes32ToBytes32Map storage map,
bytes32 key,
bytes32 value
) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
*/
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
// UintToUintMap
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
UintToUintMap storage map,
uint256 key,
uint256 value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToUintMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
// UintToAddressMap
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
UintToAddressMap storage map,
uint256 key,
address value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
// AddressToUintMap
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
AddressToUintMap storage map,
address key,
uint256 value
) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
// Bytes32ToUintMap
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(
Bytes32ToUintMap storage map,
bytes32 key,
uint256 value
) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, uint256(value));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, uint256(value));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
//////////////////////////////////////////////////
// CUSTOM IMPLEMENTATIONS
//////////////////////////////////////////////////
// UintToIntMap
// It is very specific custom structure specific for game mechanics.
struct UintToIntMap {
Bytes32ToBytes32Map _inner;
}
/// @dev Attention! Use it wisely, with properly checks.
function _set(
UintToIntMap storage map,
uint256 key,
int256 value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint(value)));
}
function setUint(
UintToIntMap storage map,
uint256 key,
uint256 value
) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
function remove(UintToIntMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
function contains(UintToIntMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
function length(UintToIntMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function _at(UintToIntMap storage map, uint256 index) internal view returns (uint256, int256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), int256(uint(value)));
}
function atUint(UintToIntMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
int _v = int256(uint(value));
if (_v < 0) {
_v = 0;
}
return (uint256(key), uint(_v));
}
function tryGet(UintToIntMap storage map, uint256 key) internal view returns (bool, int256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, int256(uint(value)));
}
function _get(UintToIntMap storage map, uint256 key) internal view returns (int256) {
return int256(uint(get(map._inner, bytes32(key))));
}
function getUint(UintToIntMap storage map, uint256 key) internal view returns (uint256) {
int value = int256(uint(get(map._inner, bytes32(key))));
if (value < 0) {
value = 0;
}
return uint(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex;
// Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "./ERC721Upgradeable.sol";
import "./IERC721Enumerable.sol";
import "./Initializable.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 ERC721EnumerableUpgradeable is Initializable, ERC721Upgradeable, IERC721Enumerable {
function __ERC721Enumerable_init() internal view {
_onlyInitializing();
}
function __ERC721Enumerable_init_unchained() internal view {
_onlyInitializing();
}
// 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, ERC721Upgradeable) 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 < ERC721Upgradeable.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 < ERC721EnumerableUpgradeable.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 = ERC721Upgradeable.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 = ERC721Upgradeable.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();
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[46] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./IERC721Metadata.sol";
import "./Address.sol";
import "./Strings.sol";
import "./ERC165.sol";
import "./Initializable.sol";
import "../relay/ERC2771Context.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 ERC721Upgradeable is Initializable, ERC2771Context, 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.
*/
function __ERC721_init(string memory name_, string memory symbol_) internal {
_onlyInitializing();
__ERC721_init_unchained(name_, symbol_);
}
function __ERC721_init_unchained(string memory name_, string memory symbol_) internal {
_onlyInitializing();
_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 = ERC721Upgradeable.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721Upgradeable.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721Upgradeable.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[44] private __gap;
}// 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;
/**
* @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 "./IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.0;
import "./Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !Address.isContract(address(this));
}
// ---------------- Additional functions for reduce contract size
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
function _initializer() internal {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "initialized");
if (!_initializing) {
_initializing = true;
_initialized = true;
}
}
function _finishInitializer() internal {
if (!_initializing) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
function _onlyInitializing() internal view {
require(_initializing, "initializing");
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a / b + (a % b == 0 ? 0 : 1);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import "../openzeppelin/Initializable.sol";
import "../interfaces/IControllable.sol";
import "../interfaces/IController.sol";
import "../lib/SlotsLib.sol";
/// @title Implement basic functionality for any contract that require strict control
/// @dev Can be used with upgradeable pattern.
/// Require call __Controllable_init() in any case.
/// @author belbix
abstract contract Controllable is Initializable, IControllable {
using SlotsLib for bytes32;
/// @notice Version of the contract
/// @dev Should be incremented when contract changed
string public constant CONTROLLABLE_VERSION = "1.0.0";
bytes32 internal constant _CONTROLLER_SLOT = bytes32(uint256(keccak256("eip1967.controllable.controller")) - 1);
bytes32 internal constant _CREATED_SLOT = bytes32(uint256(keccak256("eip1967.controllable.created")) - 1);
bytes32 internal constant _CREATED_BLOCK_SLOT = bytes32(uint256(keccak256("eip1967.controllable.created_block")) - 1);
bytes32 internal constant _REVISION_SLOT = bytes32(uint256(keccak256("eip1967.controllable.revision")) - 1);
bytes32 internal constant _PREVIOUS_LOGIC_SLOT = bytes32(uint256(keccak256("eip1967.controllable.prev_logic")) - 1);
event ContractInitialized(address controller, uint ts, uint block);
event RevisionIncreased(uint value, address oldLogic);
// init implementation contract
constructor() initializer {}
/// @notice Initialize contract after setup it as proxy implementation
/// Save block.timestamp in the "created" variable
/// @dev Use it only once after first logic setup
/// @param controller_ Controller address
function __Controllable_init(address controller_) public {
_onlyInitializing();
require(controller_ != address(0), "Zero controller");
_CONTROLLER_SLOT.set(controller_);
_CREATED_SLOT.set(block.timestamp);
_CREATED_BLOCK_SLOT.set(block.number);
emit ContractInitialized(controller_, block.timestamp, block.number);
}
/// @dev Return true if given address is controller
function isController(address _value) public override view returns (bool) {
return _value == controller();
}
/// @notice Return true if given address is setup as governance in Controller
function isGovernance(address _value) public override view returns (bool) {
return IController(controller()).governance() == _value;
}
/// @dev Contract upgrade counter
function revision() external view override returns (uint) {
return _REVISION_SLOT.getUint();
}
/// @dev Previous logic implementation
function previousImplementation() external view override returns (address) {
return _PREVIOUS_LOGIC_SLOT.getAddress();
}
// ************* SETTERS/GETTERS *******************
/// @notice Return controller address saved in the contract slot
function controller() public view override returns (address) {
return _CONTROLLER_SLOT.getAddress();
}
/// @notice Return creation timestamp
/// @return Creation timestamp
function created() external view override returns (uint256) {
return _CREATED_SLOT.getUint();
}
/// @notice Return creation block number
/// @return Creation block number
function createdBlock() external override view returns (uint256) {
return _CREATED_BLOCK_SLOT.getUint();
}
/// @dev Revision should be increased on each contract upgrade
function increaseRevision(address oldLogic) external override {
require(msg.sender == address(this), "Increase revision forbidden");
uint r = _REVISION_SLOT.getUint() + 1;
_REVISION_SLOT.set(r);
_PREVIOUS_LOGIC_SLOT.set(oldLogic);
emit RevisionIncreased(r, oldLogic);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol)
pragma solidity ^0.8.1;
/**
* @dev Context variant with ERC2771 support.
*/
// based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/metatx/ERC2771Context.sol
abstract contract ERC2771Context {
// for whitelist new relayers need to add new constants and update proxies
// address private constant GELATO_RELAY = 0xaBcC9b596420A9E9172FD5938620E265a0f9Df92;
// address private constant GELATO_RELAY_ERC_2771 = 0xb539068872230f20456CF38EC52EF2f91AF4AE49;
// address private constant GELATO_RELAY_CONCURRENT_ERC_2771 = 0x8598806401A63Ddf52473F1B3C55bC9E33e2d73b;
// address private constant GELATO_RELAY_1_BALANCE = 0x75bA5Af8EFFDCFca32E1e288806d54277D1fde99;
address private constant GELATO_RELAY_1_BALANCE_ERC_2771 = 0xd8253782c45a12053594b9deB72d8e8aB2Fca54c;
// address private constant GELATO_RELAY_1_BALANCE_CONCURRENT_ERC_2771 = 0xc65d82ECE367EF06bf2AB791B3f3CF037Dc0e816;
function isTrustedForwarder(address forwarder) public view virtual returns (bool){
return forwarder == GELATO_RELAY_1_BALANCE_ERC_2771;
}
function _msgSender() internal view virtual returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
/// @solidity memory-safe-assembly
assembly {
sender := shr(96, calldataload(sub(calldatasize(), 20)))
}
return sender;
} else {
return msg.sender;
}
}
function _msgData() internal view virtual returns (bytes calldata) {
if (isTrustedForwarder(msg.sender)) {
return msg.data[: msg.data.length - 20];
} else {
return msg.data;
}
}
/// @notice Return true if given address is not a smart contract but a wallet address.
/// @dev It is not 100% guarantee after EIP-3074 implementation, use it as an additional check.
/// @return true if the address is a wallet.
function _isNotSmartContract() internal view returns (bool) {
return isTrustedForwarder(msg.sender) || msg.sender == tx.origin;
}
}{
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 150
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {
"contracts/lib/ItemLib.sol": {
"ItemLib": "0x00379dd90b2a337c4652e286e4fbceadef940a21"
}
}
}Contract ABI
API[{"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":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"consumedId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"augmentationLevel","type":"uint256"}],"name":"Augmented","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"BaseDurabilityChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"BaseUriChanged","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bool[]","name":"increase","type":"bool[]"}],"indexed":false,"internalType":"struct IConsumableItem.GenerateConsumableInfo","name":"info","type":"tuple"},{"components":[{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"life","type":"uint256"},{"internalType":"uint256","name":"mana","type":"uint256"},{"internalType":"uint256","name":"lifeChances","type":"uint256"}],"indexed":false,"internalType":"struct IStatController.ChangeableStats","name":"stats","type":"tuple"}],"name":"ConsumableInfoChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"controller","type":"address"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"block","type":"uint256"}],"name":"ContractInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Destroyed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"heroToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"heroTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemSlot","type":"uint256"}],"name":"Equipped","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"mins","type":"uint256[]"},{"internalType":"uint256[]","name":"maxs","type":"uint256[]"},{"internalType":"uint256[]","name":"chances","type":"uint256[]"},{"internalType":"uint256","name":"minRandomAttributes","type":"uint256"},{"internalType":"uint256","name":"maxRandomAttributes","type":"uint256"}],"indexed":false,"internalType":"struct IItem.GenerateInfo","name":"info","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"mins","type":"uint256[]"},{"internalType":"uint256[]","name":"maxs","type":"uint256[]"},{"internalType":"uint256[]","name":"chances","type":"uint256[]"},{"internalType":"uint256","name":"minRandomAttributes","type":"uint256"},{"internalType":"uint256","name":"maxRandomAttributes","type":"uint256"}],"indexed":false,"internalType":"struct IItem.GenerateInfo","name":"negativeInfo","type":"tuple"}],"name":"GenInfoChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"consumedItemId","type":"uint256"}],"name":"ItemRepaired","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rarity","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"consumedId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"augmentationLevel","type":"uint256"}],"name":"NotAugmented","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDurability","type":"uint256"}],"name":"ReduceDurability","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint256","name":"strength","type":"uint256"},{"internalType":"uint256","name":"dexterity","type":"uint256"},{"internalType":"uint256","name":"vitality","type":"uint256"},{"internalType":"uint256","name":"energy","type":"uint256"}],"indexed":false,"internalType":"struct IStatController.CoreAttributes","name":"requirements","type":"tuple"}],"name":"RequirementsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"oldLogic","type":"address"}],"name":"RevisionIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"heroToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"heroTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"itemSlot","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"TakenOff","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"UniqueUriChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"uri","type":"string"},{"indexed":false,"internalType":"uint256","name":"rarity","type":"uint256"}],"name":"UriByRarityChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"hero","type":"address"},{"indexed":false,"internalType":"uint256","name":"heroId","type":"uint256"}],"name":"Used","type":"event"},{"inputs":[],"name":"CONSUMABLE_ITEM_BASE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONTROLLABLE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ITEM_BASE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NFT_BASE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"controller_","type":"address"}],"name":"__Controllable_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"consumedItemId","type":"uint256"}],"name":"augment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"augmentToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"augmentTokenAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"augmentationLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseDurability","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"consumableAttributesAndStats","outputs":[{"internalType":"uint256[]","name":"positive","type":"uint256[]"},{"internalType":"uint256[]","name":"negative","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"life","type":"uint256"},{"internalType":"uint256","name":"mana","type":"uint256"},{"internalType":"uint256","name":"lifeChances","type":"uint256"}],"internalType":"struct IStatController.ChangeableStats","name":"stats","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"created","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createdBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"destroy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"heroToken","type":"address"},{"internalType":"uint256","name":"heroTokenId","type":"uint256"},{"internalType":"uint256","name":"itemSlot","type":"uint256"}],"name":"equip","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"equipped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"equippedOn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"oldLogic","type":"address"}],"name":"increaseRevision","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller_","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"string","name":"uri_","type":"string"},{"internalType":"address","name":"augmentToken_","type":"address"},{"internalType":"uint256","name":"augmentTokenAmount_","type":"uint256"},{"internalType":"uint256","name":"itemLevel_","type":"uint256"},{"internalType":"enum IItem.ItemType","name":"itemType_","type":"uint8"},{"internalType":"uint256","name":"baseDurability_","type":"uint256"}],"name":"initItem","outputs":[],"stateMutability":"nonpayable","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":"isAttackItem","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isBuffItem","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isConsumableItem","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_value","type":"address"}],"name":"isController","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_value","type":"address"}],"name":"isGovernance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isItem","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"itemAttributes","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"itemDurability","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"itemLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"itemMetaType","outputs":[{"internalType":"enum IItem.ItemMetaType","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"itemRarity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"itemType","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"negativeItemAttributes","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"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":"previousImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"dungeonBiomeLevel","type":"uint256"}],"name":"reduceDurability","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"consumedItemId","type":"uint256"}],"name":"repairDurability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requirementAttributes","outputs":[{"components":[{"internalType":"uint256","name":"strength","type":"uint256"},{"internalType":"uint256","name":"dexterity","type":"uint256"},{"internalType":"uint256","name":"vitality","type":"uint256"},{"internalType":"uint256","name":"energy","type":"uint256"}],"internalType":"struct IStatController.CoreAttributes","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revision","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":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"score","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setBaseDurability","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setBaseUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bool[]","name":"increase","type":"bool[]"}],"internalType":"struct IConsumableItem.GenerateConsumableInfo","name":"consumableGenerateInfo_","type":"tuple"},{"components":[{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"experience","type":"uint256"},{"internalType":"uint256","name":"life","type":"uint256"},{"internalType":"uint256","name":"mana","type":"uint256"},{"internalType":"uint256","name":"lifeChances","type":"uint256"}],"internalType":"struct IStatController.ChangeableStats","name":"consumableStatsInfo_","type":"tuple"}],"name":"setConsumableInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"mins","type":"uint256[]"},{"internalType":"uint256[]","name":"maxs","type":"uint256[]"},{"internalType":"uint256[]","name":"chances","type":"uint256[]"},{"internalType":"uint256","name":"minRandomAttributes","type":"uint256"},{"internalType":"uint256","name":"maxRandomAttributes","type":"uint256"}],"internalType":"struct IItem.GenerateInfo","name":"_info","type":"tuple"},{"components":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"mins","type":"uint256[]"},{"internalType":"uint256[]","name":"maxs","type":"uint256[]"},{"internalType":"uint256[]","name":"chances","type":"uint256[]"},{"internalType":"uint256","name":"minRandomAttributes","type":"uint256"},{"internalType":"uint256","name":"maxRandomAttributes","type":"uint256"}],"internalType":"struct IItem.GenerateInfo","name":"_negativeInfo","type":"tuple"},{"internalType":"uint256","name":"strengthReq","type":"uint256"},{"internalType":"uint256","name":"dexterityReq","type":"uint256"},{"internalType":"uint256","name":"vitalityReq","type":"uint256"},{"internalType":"uint256","name":"energyReq","type":"uint256"},{"internalType":"uint256","name":"defaultRarity_","type":"uint256"}],"name":"setItemMeta","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint256","name":"rarity","type":"uint256"}],"name":"setItemUriByRarity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setUniqueUri","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":"tokenId","type":"uint256"},{"internalType":"address","name":"heroToken","type":"address"},{"internalType":"uint256","name":"heroTokenId","type":"uint256"},{"internalType":"uint256","name":"itemSlot","type":"uint256"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"bool","name":"broken","type":"bool"}],"name":"takeOff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"heroToken","type":"address"},{"internalType":"uint256","name":"heroTokenId","type":"uint256"}],"name":"use","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405260016065553480156200001657600080fd5b50600054610100900460ff16620000345760005460ff161562000038565b303b155b620000a05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000c3576000805461ffff19166101011790555b8015620000d6576000805461ff00191690555b5060978054600160ff19918216811790925560d980549091169091179055615ef680620001046000396000f3fe608060405234801561001057600080fd5b50600436106104075760003560e01c80636c0360eb11610220578063b423799e11610130578063d909ea5f116100b8578063f020c59411610087578063f020c594146108b3578063f5470d7b146108f3578063f77c4791146108fc578063fcc78fa514610904578063ffa1ad741461072157600080fd5b8063d909ea5f146108b3578063dee1f0e4146108ba578063e327a6af146108cd578063e985e9c5146108e057600080fd5b8063b9114ce1116100ff578063b9114ce114610854578063bc0d396b14610867578063c87b56dd1461087a578063d1089f331461088d578063d1730f1f146108a057600080fd5b8063b423799e14610805578063b429afeb14610825578063b75f4d8f14610838578063b88d4fde1461084157600080fd5b80639845f17a116101b3578063a0bcfc7f11610182578063a0bcfc7f1461078e578063a0fe0f51146107a1578063a22cb465146107b4578063a5d3bafb146107c7578063a60138a7146107f257600080fd5b80639845f17a1461074d5780639d0bcca0146107605780639d118770146107685780639e2cfb0f1461077b57600080fd5b8063820e5865116101ef578063820e5865146106ec5780638e776f9c1461070e578063936725ec1461072157806395d89b411461074557600080fd5b80636c0360eb146106a957806370a08231146106b1578063718df8fa146106c45780637cc96380146106e457600080fd5b806336c944851161031b5780634f558e79116102ae578063583eab451161027d578063583eab451461063b5780636352211e1461065b57806364f2d7531461066e57806366679a0614610683578063681641381461069657600080fd5b80634f558e79146105ef5780634f6ccce7146106025780634fac6ccd14610615578063572b6c051461062857600080fd5b80633e3008b6116102ea5780633e3008b6146105c157806342842e0e146105d45780634593144c146105e75780634dd8481d1461055e57600080fd5b806336c94485146105895780633710c70a1461059c5780633c97cf60146105af5780633d54e23b146105b857600080fd5b80631f2a5ace1161039e5780632f745c591161036d5780632f745c5914610543578063325a19f11461055657806332d671a11461055e57806335320ba21461058257806335798ed01461058257600080fd5b80631f2a5ace146104ea578063203e597c1461050e57806323b872dd146105215780632e2da5171461053457600080fd5b80631249c58b116103da5780631249c58b1461048957806318160ddd1461049f5780631a8abe9a146104a75780631c001d77146104ca57600080fd5b806301ffc9a71461040c57806306fdde0314610434578063081812fc14610449578063095ea7b314610474575b600080fd5b61041f61041a366004614374565b61091c565b60405190151581526020015b60405180910390f35b61043c610947565b60405161042b91906143d7565b61045c6104573660046143ea565b6109d9565b6040516001600160a01b03909116815260200161042b565b610487610482366004614428565b610a66565b005b610491610b88565b60405190815260200161042b565b603554610491565b61041f6104b53660046143ea565b609f6020526000908152604090205460ff1681565b6104dd6104d83660046143ea565b610b9f565b60405161042b9190614490565b61043c60405180604001604052806005815260200164312e302e3360d81b81525081565b61048761051c3660046144a3565b610bb9565b61048761052f3660046144c5565b610c33565b600460405161042b919061451c565b610491610551366004614428565b610c6b565b610491610d01565b61043c60405180604001604052806005815260200164312e302e3160d81b81525081565b600161041f565b610487610597366004614724565b610d35565b6104dd6105aa3660046143ea565b610f5a565b61049160985481565b61049160995481565b6104876105cf3660046147b3565b610f74565b6104876105e23660046144c5565b6112b7565b6104916112d2565b61041f6105fd3660046143ea565b611302565b6104916106103660046143ea565b61130d565b6104876106233660046147f0565b6113a0565b61041f6106363660046147f0565b6114d3565b6104916106493660046143ea565b609e6020526000908152604090205481565b61045c6106693660046143ea565b6114f5565b610676611510565b60405161042b919061480d565b6104876106913660046148be565b611568565b6104876106a4366004614995565b6115d3565b61043c611625565b6104916106bf3660046147f0565b61162f565b6104916106d23660046143ea565b60a26020526000908152604090205481565b6104916116b6565b6106ff6106fa3660046143ea565b6116e6565b60405161042b939291906149d9565b61048761071c366004614a47565b61179f565b61043c604051806040016040528060058152602001640312e302e360dc1b81525081565b61043c611b74565b61048761075b366004614aae565b611b83565b61045c611ff7565b6104876107763660046143ea565b612027565b6104876107893660046143ea565b6121ef565b61048761079c366004614ad5565b612233565b6104876107af3660046147f0565b612277565b6104876107c2366004614b09565b61239c565b6104916107d5366004614b42565b60b460209081526000928352604080842090915290825290205481565b610487610800366004614b67565b6123ae565b6104916108133660046143ea565b60a06020526000908152604090205481565b61041f6108333660046147f0565b612400565b610491609b5481565b61048761084f366004614bad565b612425565b610487610862366004614c9b565b61245e565b6104916108753660046144a3565b61251b565b61043c6108883660046143ea565b612683565b61048761089b3660046144a3565b612794565b6104916108ae3660046143ea565b6129ce565b600061041f565b61041f6108c83660046147f0565b612ac3565b61041f6108db366004614428565b612b48565b61041f6108ee366004614dc4565b612b6e565b610491609a5481565b61045c612b9c565b60975461045c9061010090046001600160a01b031681565b60006001600160e01b0319821663780e9d6360e01b1480610941575061094182612bcc565b92915050565b60606001805461095690614df2565b80601f016020809104026020016040519081016040528092919081815260200182805461098290614df2565b80156109cf5780601f106109a4576101008083540402835291602001916109cf565b820191906000526020600020905b8154815290600101906020018083116109b257829003601f168201915b5050505050905090565b60006109e482612c1c565b610a4a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610a71826114f5565b9050806001600160a01b0316836001600160a01b031603610ade5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610a41565b806001600160a01b0316610af0612c39565b6001600160a01b03161480610b0c5750610b0c816108ee612c39565b610b795760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608401610a41565b610b838383612c5b565b505050565b6000610b92612cc9565b610b9a612d74565b905090565b6000818152609c6020526040902060609061094190612f87565b610bc1613016565b610bdd5760405162461bcd60e51b8152600401610a4190614e2c565b610be68261302e565b610bef8161302e565b60405162461bcd60e51b815260206004820152600a602482015269636f6e73756d61626c6560b01b6044820152606401610a41565b60405180910390a15b50505050565b610c44610c3e612c39565b826130aa565b610c605760405162461bcd60e51b8152600401610a4190614e49565b610b8383838361316c565b6000610c768361162f565b8210610cd85760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610a41565b506001600160a01b03919091166000908152603360209081526040808320938352929052205490565b6000610b9a610d3160017f6f55f470bdc9cb5f04223fd822021061668e4dccb43e8727b295106dc9769c8b614eb0565b5490565b610d3d613313565b6002876080015110610d7d5760405162461bcd60e51b81526020600482015260096024820152683bb937b7339036b4b760b91b6044820152606401610a41565b86518051889160a391610d97918391602090910190614262565b506020828101518051610db09260018501920190614262565b5060408201518051610dcc916002840191602090910190614262565b5060608201518051610de8916003840191602090910190614262565b506080820151600482015560a09091015160059091015585518051879160a991610e19918391602090910190614262565b506020828101518051610e329260018501920190614262565b5060408201518051610e4e916002840191602090910190614262565b5060608201518051610e6a916003840191602090910190614262565b50608082810151600483015560a0909201516005909101556040805180830182528781526020808201889052818301879052606091820186905260af89905560b088905560b187905560b286905560b38590556097805460ff191660011790558251938401835288845283018790528282018690528201849052517f602b6148a680b6852202136cd0ed63398bb67e9b54ab8248ddcf8cc87928c24991610f109161480d565b60405180910390a17f7dc32c0d4744428a5321dfa2ba3882a2f7506b6484e465132ecabd335cdb29798787604051610f49929190614f46565b60405180910390a150505050505050565b6000818152609d6020526040902060609061094190612f87565b6000610f7e612b9c565b9050610f898561302e565b610f91613016565b610fad5760405162461bcd60e51b8152600401610a4190614e2c565b6000858152609f602052604090205460ff1615610fdc5760405162461bcd60e51b8152600401610a4190614f74565b806001600160a01b03166318d928316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561101a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103e9190614f96565b1561105b5760405162461bcd60e51b8152600401610a4190614fb3565b60006001600160a01b0316846001600160a01b03166396336b306040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c89190614fd3565b6001600160a01b0316036110ee5760405162461bcd60e51b8152600401610a4190614ff0565b7300379dd90b2a337c4652e286e4fbceadef940a21634c5ab701609c609d604051806101400160405280611120612c39565b6001600160a01b03168152602001866001600160a01b031681526020018a8152602001896001600160a01b03168152602001888152602001878152602001609a548152602001609b54815260200160a260008c815260200190815260200160002054815260200160af6040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250508152506040518463ffffffff1660e01b81526004016111dd93929190615013565b60006040518083038186803b1580156111f557600080fd5b505af4158015611209573d6000803e3d6000fd5b5050505061122f611218612c39565b8587604051806020016040528060008152506133bd565b6000858152609f60209081526040808320805460ff1916600117905560b482528083206001600160a01b03881680855290835292819020869055805188815291820192909252908101849052606081018390527f3be07f3d969f411bb95cc5b5af0235965db26ca648e7df2d84a0424d0086aabf906080015b60405180910390a15050505050565b610b8383838360405180602001604052806000815250612425565b6000610b9a610d3160017f812a673dfca07956350df10f8a654925f561d7a0da09bdbe79e653939a14d9f1614eb0565b600061094182612c1c565b600061131860355490565b821061137b5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610a41565b6035828154811061138e5761138e6150e0565b90600052602060002001549050919050565b3330146113ef5760405162461bcd60e51b815260206004820152601b60248201527f496e637265617365207265766973696f6e20666f7262696464656e00000000006044820152606401610a41565b600061141f610d3160017f22573091f17911fb166032a3d9e0554aa73d31b7b7ddea4a4dd2995650af84bd614eb0565b61142a9060016150f6565b905061145e8161145b60017f22573091f17911fb166032a3d9e0554aa73d31b7b7ddea4a4dd2995650af84bd614eb0565b55565b61148d8261145b60017fbfaaa2fb63266ff27c2da975f5894955056f50419af651a81f6c5060581857e4614eb0565b604080518281526001600160a01b03841660208201527ff27e2ef832a4eb8ed8ec553b875eecd44764cda95b1c24170e281539e0a869c891015b60405180910390a15050565b6001600160a01b031673d8253782c45a12053594b9deb72d8e8ab2fca54c1490565b6000908152600360205260409020546001600160a01b031690565b61153b6040518060800160405280600081526020016000815260200160008152602001600081525090565b506040805160808101825260af54815260b054602082015260b1549181019190915260b254606082015290565b6115706133f0565b61157c88888b89613469565b60978054610100600160a81b0319166101006001600160a01b038816021790556098849055609983905581600b8111156115b8576115b8614506565b609a55609b8190556115c86134c5565b505050505050505050565b6115db613313565b600081815260a1602052604090206115f38382615159565b507f29f443087b03c724ded11254c74c7211dcb5e505b280d10747d67f3a0227879082826040516114c7929190615218565b6060610b9a6134e1565b60006001600160a01b03821661169a5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610a41565b506001600160a01b031660009081526004602052604090205490565b6000610b9a610d3160017f22573091f17911fb166032a3d9e0554aa73d31b7b7ddea4a4dd2995650af84bd614eb0565b60608061171b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b600084815260da6020526040902061173290612f87565b600085815260db6020526040902061174990612f87565b600095865260dc6020908152604096879020875160a08101895281548152600182015492810192909252600281015497820197909752600387015460608201526004909601546080870152909590949350915050565b60006117a9612b9c565b90506117b4816134f0565b6000878152609f602052604090205460ff1680156117f35750600087815260b4602090815260408083206001600160a01b038a16845290915290205485145b61182b5760405162461bcd60e51b815260206004820152600960248201526808595c5d5a5c1c195960ba1b6044820152606401610a41565b609a54600081900361186c5760405162461bcd60e51b815260206004820152600a602482015269636f6e73756d61626c6560b01b6044820152606401610a41565b6000826001600160a01b0316628e96916040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cf9190614fd3565b604051630c6222cb60e01b81526001600160a01b038a81166004830152602482018a9052604482018590526064820189905230608483015260a482018c9052600060c483015291925090821690630c6222cb9060e401600060405180830381600087803b15801561193f57600080fd5b505af1158015611953573d6000803e3d6000fd5b50505050831561196d57600089815260a260205260408120555b806001600160a01b03166324a0b0356040518060a001604052808b6001600160a01b031681526020018a81526020016119b7609c60008f8152602001908152602001600020612f87565b8152600060208201819052604091820152516001600160e01b031960e084901b1681526119e7919060040161523a565b600060405180830381600087803b158015611a0157600080fd5b505af1158015611a15573d6000803e3d6000fd5b50505050806001600160a01b03166324a0b0356040518060a001604052808b6001600160a01b031681526020018a8152602001611a63609d60008f8152602001908152602001600020612f87565b8152600160208201526000604091820152516001600160e01b031960e084901b168152611a93919060040161523a565b600060405180830381600087803b158015611aad57600080fd5b505af1158015611ac1573d6000803e3d6000fd5b50505060008a8152609f60209081526040808320805460ff1916905560b482528083206001600160a01b038d168452825280832083905580519182019052908152611b129150899087908c906133bd565b604080518a81526001600160a01b038a811660208301528183018a9052606082018990528716608082015290517fc64e9512c33531b1b4767eb306c4690a87eb36bc541a383fa538499648e9a9f49181900360a00190a1505050505050505050565b60606002805461095690614df2565b6000611b8d612b9c565b9050611b988461302e565b611ba0613016565b611bbc5760405162461bcd60e51b8152600401610a4190614e2c565b806001600160a01b03166318d928316040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1e9190614f96565b15611c3b5760405162461bcd60e51b8152600401610a4190614fb3565b6000816001600160a01b0316628e96916040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9e9190614fd3565b60405163223e40cf60e01b81526001600160a01b038083166004830152861660248201526044810185905260af54606482015260b054608482015260b15460a482015260b25460c48201529091507300379dd90b2a337c4652e286e4fbceadef940a219063223e40cf9060e40160006040518083038186803b158015611d2357600080fd5b505af4158015611d37573d6000803e3d6000fd5b505060405163138e914f60e11b81526001600160a01b038781166004830152602482018790523060448301528416925063271d229e9150606401600060405180830381600087803b158015611d8b57600080fd5b505af1158015611d9f573d6000803e3d6000fd5b505050600086815260dc60205260409081902090516381b182cd60e01b81526001600160a01b038781166004808401919091526024830188905283546044840152600180850154606485015260028501546084850152600385015460a485015293015460c483015260e482019290925290831691506381b182cd9061010401600060405180830381600087803b158015611e3857600080fd5b505af1158015611e4c573d6000803e3d6000fd5b50505050806001600160a01b03166324a0b0356040518060a00160405280876001600160a01b03168152602001868152602001611e9a60da60008b8152602001908152602001600020612f87565b8152600160208201819052604091820152516001600160e01b031960e084901b168152611eca919060040161523a565b600060405180830381600087803b158015611ee457600080fd5b505af1158015611ef8573d6000803e3d6000fd5b50505050806001600160a01b03166324a0b0356040518060a00160405280876001600160a01b03168152602001868152602001611f4660db60008b8152602001908152602001600020612f87565b8152600060208201526001604091820152516001600160e01b031960e084901b168152611f76919060040161523a565b600060405180830381600087803b158015611f9057600080fd5b505af1158015611fa4573d6000803e3d6000fd5b50505050611fb185613071565b604080518681526001600160a01b03861660208201529081018490527f8f0c0d91ba98d7745b984165ac65d4e188c2455ccc13d5155c860f0d9246a815906060016112a8565b6000610b9a610d3160017fbfaaa2fb63266ff27c2da975f5894955056f50419af651a81f6c5060581857e4614eb0565b6000612031612b9c565b9050806001600160a01b03166325a6c51d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612071573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120959190614fd3565b60405163f2f4a8af60e01b81523360048201526001600160a01b03919091169063f2f4a8af90602401602060405180830381865afa1580156120db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ff9190614f96565b8061217c5750336001600160a01b0316816001600160a01b031663524a562f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561214d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121719190614fd3565b6001600160a01b0316145b8061219757503361218c836114f5565b6001600160a01b0316145b6121b35760405162461bcd60e51b8152600401610a4190614ff0565b6000828152609f602052604090205460ff16156121e25760405162461bcd60e51b8152600401610a4190614f74565b6121eb82613071565b5050565b6121f7613313565b609b8190556040518181527f7ef6d608ec96a3c1d48de6ceb0c0bd19618f4b93f0095308c79cd6ca4b51b187906020015b60405180910390a150565b61223b613313565b60666122478282615159565b507f87cdeaffd8e70903d6ce7cc983fac3b09ca79e83818124c98e47a1d70f8027d68160405161222891906143d7565b61227f6135e6565b6001600160a01b0381166122c75760405162461bcd60e51b815260206004820152600f60248201526e2d32b9379031b7b73a3937b63632b960891b6044820152606401610a41565b6122f68161145b60017f5165972ef41194f06c5007493031d0b927c20741adcb74403b954009fd2c3618614eb0565b6123254261145b60017f6f55f470bdc9cb5f04223fd822021061668e4dccb43e8727b295106dc9769c8b614eb0565b6123544361145b60017f812a673dfca07956350df10f8a654925f561d7a0da09bdbe79e653939a14d9f1614eb0565b604080516001600160a01b038316815242602082015243918101919091527f1a2dd071001ebf6e03174e3df5b305795a4ad5d41d8fdb9ba41dbbe23671342690606001612228565b6121eb6123a7612c39565b838361362c565b6123b6613313565b60008281526067602052604090206123ce8282615159565b507ff32b5bcd021361ac825fde09ff2121b0e5783f9f993196194fab9471799e54dd82826040516114c7929190615296565b600061240a612b9c565b6001600160a01b0316826001600160a01b0316149050919050565b612436612430612c39565b836130aa565b6124525760405162461bcd60e51b8152600401610a4190614e49565b610c2d848484846133bd565b612466613313565b81518051839160dd91612480918391602090910190614262565b5060208281015180516124999260018501920190614262565b50604082015180516124b59160028401916020909101906142ad565b5050815160e05550602081015160e15560408082015160e255606082015160e355608082015160e45560d9805460ff19166001179055517fc8e30ad432142bd0dfb602223be2c9714576cc124dbcee021719e2f29cdaf0b5906114c790849084906152af565b600080612526612b9c565b9050612531816134f0565b6000816001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612571573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125959190614fd3565b600086815260a2602052604080822054609954609a54925163b3e13ad160e01b8152600481018a9052602481019290925260448201526064810191909152919250906001600160a01b0383169063b3e13ad190608401602060405180830381865afa158015612608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262c9190615375565b600087815260a2602090815260409182902083905581518981529081018390529192507feb46efb0c7198679c79853a979eb80da18892986f9942ca8873ed7c4cefb5975910160405180910390a195945050505050565b60606065548211156126c05760405162461bcd60e51b815260206004820152600660248201526508595e1a5cdd60d21b6044820152606401610a41565b600082815260676020526040812080546126d990614df2565b80601f016020809104026020016040519081016040528092919081815260200182805461270590614df2565b80156127525780601f1061272757610100808354040283529160200191612752565b820191906000526020600020905b81548152906001019060200180831161273557829003601f168201915b5050505050905080516000146127685792915050565b6000612773846136fa565b805190915015612784579392505050565b61278c6134e1565b949350505050565b600061279e612b9c565b90506127a8613016565b6127c45760405162461bcd60e51b8152600401610a4190614e2c565b6127cd8361302e565b6127d68261302e565b609b5460008190036128185760405162461bcd60e51b815260206004820152600b60248201526a216475726162696c69747960a81b6044820152606401610a41565b6000848152609f602052604090205460ff1615801561284657506000838152609f602052604090205460ff16155b6128625760405162461bcd60e51b8152600401610a4190614f74565b816001600160a01b03166318d928316040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c49190614f96565b156128e15760405162461bcd60e51b8152600401610a4190614fb3565b6128ea83613071565b7300379dd90b2a337c4652e286e4fbceadef940a2163806f099d61290c612b9c565b60975461010090046001600160a01b03166001612927612c39565b600a609854612936919061538e565b6040518663ffffffff1660e01b81526004016129569594939291906153b0565b60006040518083038186803b15801561296e57600080fd5b505af4158015612982573d6000803e3d6000fd5b505050600085815260a2602090815260409182902084905581518781529081018690527ffc4ee3fbea4df52f867d98cb796e03a5ae97157fa0c2372c6f61d4336543a7ee925001610c24565b60006129d8612b9c565b6001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190614fd3565b6001600160a01b03166351c9120d612a62609c6000868152602001908152602001600020612f87565b609b546040518363ffffffff1660e01b8152600401612a829291906153f9565b602060405180830381865afa158015612a9f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109419190615375565b6000816001600160a01b0316612ad7612b9c565b6001600160a01b0316635aa6e6756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b389190614fd3565b6001600160a01b03161492915050565b6000826001600160a01b0316612b5d836114f5565b6001600160a01b0316149392505050565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b6000610b9a610d3160017f5165972ef41194f06c5007493031d0b927c20741adcb74403b954009fd2c3618614eb0565b60006001600160e01b031982166380ac58cd60e01b1480612bfd57506001600160e01b03198216635b5e139f60e01b145b8061094157506301ffc9a760e01b6001600160e01b0319831614610941565b6000908152600360205260409020546001600160a01b0316151590565b6000612c44336114d3565b15612c56575060131936013560601c90565b503390565b600081815260056020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612c90826114f5565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b612cd1612b9c565b604051633ec963c960e01b81523360048201526001600160a01b039190911690633ec963c990602401602060405180830381865afa158015612d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3b9190614f96565b612d725760405162461bcd60e51b815260206004820152600860248201526710b23ab733b2b7b760c11b6044820152606401610a41565b565b6000612d7e6137a9565b9050612d91612d8b612c39565b826137c2565b6000612d9b612b9c565b6001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612dd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dfc9190614fd3565b6000838152609c602052604080822060b354915163fe1a90f160e01b815293945091927300379dd90b2a337c4652e286e4fbceadef940a219263fe1a90f192612e4d9287929160a3916004016154b7565b602060405180830381865af4158015612e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8e9190615375565b6000848152609d602052604090819020905163fe1a90f160e01b81529192507300379dd90b2a337c4652e286e4fbceadef940a219163fe1a90f191612ede9186919060a9906001906004016154b7565b602060405180830381865af4158015612efb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1f9190615375565b506000838152609e60209081526040808320849055609b5460a290925290912055612f49836137dc565b60408051848152602081018390527f8a9dcf4e150b1153011b29fec302d5be0c13e84fa8f56ab78587f778a32a90dd910160405180910390a1505090565b60606000612f948361383e565b60408051602b808252610580820190925291925060009190602082016105608036833701905050905060005b8281101561300e57600080612fd58784613849565b915091506000811215612fe6575060005b80848381518110612ff957612ff96150e0565b60209081029190910101525050600101612fc0565b509392505050565b6000613021336114d3565b80610b9a57505032331490565b613036612c39565b6001600160a01b0316613048826114f5565b6001600160a01b03161461306e5760405162461bcd60e51b8152600401610a4190614ff0565b50565b61307a81613865565b6040518181527ff15a2816d9b33bd70f4b57d8cfbd7ee75d3231d8c52a030fef8a86fb4adfe94790602001612228565b60006130b582612c1c565b6131165760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a41565b6000613121836114f5565b9050806001600160a01b0316846001600160a01b0316148061315c5750836001600160a01b0316613151846109d9565b6001600160a01b0316145b8061278c575061278c8185612b6e565b826001600160a01b031661317f826114f5565b6001600160a01b0316146131e35760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610a41565b6001600160a01b0382166132455760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a41565b61325083838361390c565b61325b600082612c5b565b6001600160a01b0383166000908152600460205260408120805460019290613284908490614eb0565b90915550506001600160a01b03821660009081526004602052604081208054600192906132b29084906150f6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b61331b612b9c565b604051631430d62960e21b81523360048201526001600160a01b0391909116906350c358a490602401602060405180830381865afa158015613361573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133859190614f96565b612d725760405162461bcd60e51b815260206004820152600960248201526810b232b83637bcb2b960b91b6044820152606401610a41565b6133c884848461316c565b6133d484848484613946565b610c2d5760405162461bcd60e51b8152600401610a41906154ef565b600054610100900460ff1661340b5760005460ff161561340f565b303b155b6134495760405162461bcd60e51b815260206004820152600b60248201526a1a5b9a5d1a585b1a5e995960aa1b6044820152606401610a41565b600054610100900460ff16612d72576000805461ffff1916610101179055565b6134716135e6565b61347b8484613a4e565b61348482612277565b600160655560666134958282615159565b507f87cdeaffd8e70903d6ce7cc983fac3b09ca79e83818124c98e47a1d70f8027d681604051610c2491906143d7565b600054610100900460ff16612d72576000805461ff0019169055565b60606066805461095690614df2565b60405163ba79bf5f60e01b81523360048201526001600160a01b0382169063ba79bf5f90602401602060405180830381865afa158015613534573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135589190614f96565b806135ca5750336001600160a01b0316816001600160a01b031663524a562f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130489190614fd3565b61306e5760405162461bcd60e51b8152600401610a4190614ff0565b600054610100900460ff16612d725760405162461bcd60e51b815260206004820152600c60248201526b696e697469616c697a696e6760a01b6044820152606401610a41565b816001600160a01b0316836001600160a01b03160361368d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a41565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000818152609e6020908152604080832054835260a1909152902080546060919061372490614df2565b80601f016020809104026020016040519081016040528092919081815260200182805461375090614df2565b801561379d5780601f106137725761010080835404028352916020019161379d565b820191906000526020600020905b81548152906001019060200180831161378057829003601f168201915b50505050509050919050565b6065546000906137ba8160016150f6565b606555919050565b6121eb828260405180602001604052806000815250613a60565b600081815260da6020908152604080832060db909252909120613800919083613a93565b600091825260dc6020908152604092839020825181559082015160018201559181015160028301556060810151600383015560800151600490910155565b600061094182613dba565b60008080806138588686613dc5565b9097909650945050505050565b6000613870826114f5565b905061387e8160008461390c565b613889600083612c5b565b6001600160a01b03811660009081526004602052604081208054600192906138b2908490614eb0565b909155505060008281526003602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000818152609f602052604090205460ff161561393b5760405162461bcd60e51b8152600401610a4190614f74565b610b83838383613df0565b60006001600160a01b0384163b15613a4357836001600160a01b031663150b7a0261396f612c39565b8786866040518563ffffffff1660e01b81526004016139919493929190615541565b6020604051808303816000875af19250505080156139cc575060408051601f3d908101601f191682019092526139c99181019061557e565b60015b613a29573d8080156139fa576040519150601f19603f3d011682016040523d82523d6000602084013e6139ff565b606091505b508051600003613a215760405162461bcd60e51b8152600401610a41906154ef565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061278c565b506001949350505050565b613a566135e6565b6121eb8282613ea8565b613a6a8383613ec9565b613a776000848484613946565b610b835760405162461bcd60e51b8152600401610a41906154ef565b613ac56040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000613acf612b9c565b6001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b309190614fd3565b9050600080826001600160a01b0316635cb8980f60dd6040518263ffffffff1660e01b8152600401613b62919061559b565b600060405180830381865afa158015613b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613ba79190810190615dc3565b91509150600080846001600160a01b0316635027f3848560b3546040518363ffffffff1660e01b8152600401613bde929190615e1c565b6000604051808303816000875af1158015613bfd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c259190810190615e2f565b509150915060005b8151811015613c91576000828281518110613c4a57613c4a6150e0565b602002602001015190506000848381518110613c6857613c686150e0565b6020026020010151905081600014613c8757613c858c8284614008565b505b5050600101613c2d565b5060b354604051631409fce160e21b815260009182916001600160a01b03891691635027f38491613cc6918991600401615e1c565b6000604051808303816000875af1158015613ce5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d0d9190810190615e2f565b509150915060005b8151811015613d79576000828281518110613d3257613d326150e0565b602002602001015190506000848381518110613d5057613d506150e0565b6020026020010151905081600014613d6f57613d6d8d8284614008565b505b5050600101613d15565b50506040805160a08101825260e054815260e154602082015260e2549181019190915260e354606082015260e45460808201529a9950505050505050505050565b600061094182614015565b60008080613dd3858561401f565b600081815260029690960160205260409095205494959350505050565b6001600160a01b038316613e4b57613e4681603580546000838152603660205260408120829055600182018355919091527fcfa4bec1d3298408bb5afcfcd9c430549c5b31f8aa5c5848151c0a55f473c34d0155565b613e6e565b816001600160a01b0316836001600160a01b031614613e6e57613e6e8382614032565b6001600160a01b038216613e8557610b83816140cf565b826001600160a01b0316826001600160a01b031614610b8357610b83828261417e565b613eb06135e6565b6001613ebc8382615159565b506002610b838282615159565b6001600160a01b038216613f1f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a41565b613f2881612c1c565b15613f755760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a41565b613f816000838361390c565b6001600160a01b0382166000908152600460205260408120805460019290613faa9084906150f6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600061278c8484846141c2565b6000610941825490565b600061402b83836141df565b9392505050565b6000600161403f8461162f565b6140499190614eb0565b60008381526034602052604090205490915080821461409c576001600160a01b03841660009081526033602090815260408083208584528252808320548484528184208190558352603490915290208190555b5060009182526034602090815260408084208490556001600160a01b039094168352603381528383209183525290812055565b6035546000906140e190600190614eb0565b60008381526036602052604081205460358054939450909284908110614109576141096150e0565b90600052602060002001549050806035838154811061412a5761412a6150e0565b600091825260208083209091019290925582815260369091526040808220849055858252812055603580548061416257614162615eaa565b6001900381819060005260206000200160009055905550505050565b60006141898361162f565b6001600160a01b039093166000908152603360209081526040808320868452825280832085905593825260349052919091209190915550565b6000828152600284016020526040812082905561278c8484614209565b60008260000182815481106141f6576141f66150e0565b9060005260206000200154905092915050565b600081815260018301602052604081205461402b9084908490849061425a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610941565b506000610941565b82805482825590600052602060002090810192821561429d579160200282015b8281111561429d578251825591602001919060010190614282565b506142a9929150614349565b5090565b82805482825590600052602060002090601f0160209004810192821561429d5791602002820160005b8382111561431357835183826101000a81548160ff02191690831515021790555092602001926001016020816000010492830192600103026142d6565b80156143405782816101000a81549060ff0219169055600101602081600001049283019260010302614313565b50506142a99291505b5b808211156142a9576000815560010161434a565b6001600160e01b03198116811461306e57600080fd5b60006020828403121561438657600080fd5b813561402b8161435e565b6000815180845260005b818110156143b75760208185018101518683018201520161439b565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061402b6020830184614391565b6000602082840312156143fc57600080fd5b5035919050565b6001600160a01b038116811461306e57600080fd5b803561442381614403565b919050565b6000806040838503121561443b57600080fd5b823561444681614403565b946020939093013593505050565b60008151808452602080850194506020840160005b8381101561448557815187529582019590820190600101614469565b509495945050505050565b60208152600061402b6020830184614454565b600080604083850312156144b657600080fd5b50508035926020909101359150565b6000806000606084860312156144da57600080fd5b83356144e581614403565b925060208401356144f581614403565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b602081016005831061453057614530614506565b91905290565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b038111828210171561456e5761456e614536565b60405290565b604051606081016001600160401b038111828210171561456e5761456e614536565b604051601f8201601f191681016001600160401b03811182821017156145be576145be614536565b604052919050565b60006001600160401b038211156145df576145df614536565b5060051b60200190565b600082601f8301126145fa57600080fd5b8135602061460f61460a836145c6565b614596565b8083825260208201915060208460051b87010193508684111561463157600080fd5b602086015b8481101561464d5780358352918301918301614636565b509695505050505050565b600060c0828403121561466a57600080fd5b61467261454c565b905081356001600160401b038082111561468b57600080fd5b614697858386016145e9565b835260208401359150808211156146ad57600080fd5b6146b9858386016145e9565b602084015260408401359150808211156146d257600080fd5b6146de858386016145e9565b604084015260608401359150808211156146f757600080fd5b50614704848285016145e9565b6060830152506080820135608082015260a082013560a082015292915050565b600080600080600080600060e0888a03121561473f57600080fd5b87356001600160401b038082111561475657600080fd5b6147628b838c01614658565b985060208a013591508082111561477857600080fd5b506147858a828b01614658565b979a9799505050506040860135956060810135956080820135955060a0820135945060c09091013592509050565b600080600080608085870312156147c957600080fd5b8435935060208501356147db81614403565b93969395505050506040820135916060013590565b60006020828403121561480257600080fd5b813561402b81614403565b8151815260208083015190820152604080830151908201526060808301519082015260808101610941565b60006001600160401b0383111561485157614851614536565b614864601f8401601f1916602001614596565b905082815283838301111561487857600080fd5b828260208301376000602084830101529392505050565b600082601f8301126148a057600080fd5b61402b83833560208501614838565b8035600c811061442357600080fd5b60008060008060008060008060006101208a8c0312156148dd57600080fd5b6148e68a614418565b985060208a01356001600160401b038082111561490257600080fd5b61490e8d838e0161488f565b995060408c013591508082111561492457600080fd5b6149308d838e0161488f565b985060608c013591508082111561494657600080fd5b506149538c828d0161488f565b96505061496260808b01614418565b945060a08a0135935060c08a0135925061497e60e08b016148af565b91506101008a013590509295985092959850929598565b600080604083850312156149a857600080fd5b82356001600160401b038111156149be57600080fd5b6149ca8582860161488f565b95602094909401359450505050565b60e0815260006149ec60e0830186614454565b82810360208401526149fe8186614454565b91505061278c604083018480518252602081015160208301526040810151604083015260608101516060830152608081015160808301525050565b801515811461306e57600080fd5b60008060008060008060c08789031215614a6057600080fd5b863595506020870135614a7281614403565b945060408701359350606087013592506080870135614a9081614403565b915060a0870135614aa081614a39565b809150509295509295509295565b600080600060608486031215614ac357600080fd5b8335925060208401356144f581614403565b600060208284031215614ae757600080fd5b81356001600160401b03811115614afd57600080fd5b61278c8482850161488f565b60008060408385031215614b1c57600080fd5b8235614b2781614403565b91506020830135614b3781614a39565b809150509250929050565b60008060408385031215614b5557600080fd5b823591506020830135614b3781614403565b60008060408385031215614b7a57600080fd5b8235915060208301356001600160401b03811115614b9757600080fd5b614ba38582860161488f565b9150509250929050565b60008060008060808587031215614bc357600080fd5b8435614bce81614403565b93506020850135614bde81614403565b92506040850135915060608501356001600160401b03811115614c0057600080fd5b8501601f81018713614c1157600080fd5b614c2087823560208401614838565b91505092959194509250565b600060a08284031215614c3e57600080fd5b60405160a081018181106001600160401b0382111715614c6057614c60614536565b806040525080915082358152602083013560208201526040830135604082015260608301356060820152608083013560808201525092915050565b60008060c08385031215614cae57600080fd5b82356001600160401b0380821115614cc557600080fd5b9084019060608287031215614cd957600080fd5b614ce1614574565b823582811115614cf057600080fd5b614cfc888286016145e9565b82525060208084013583811115614d1257600080fd5b614d1e898287016145e9565b8284015250604084013583811115614d3557600080fd5b80850194505087601f850112614d4a57600080fd5b83359250614d5a61460a846145c6565b83815260059390931b84018101928181019089851115614d7957600080fd5b948201945b84861015614da0578535614d9181614a39565b82529482019490820190614d7e565b8060408501525050819550614db788828901614c2c565b9450505050509250929050565b60008060408385031215614dd757600080fd5b8235614de281614403565b91506020830135614b3781614403565b600181811c90821680614e0657607f821691505b602082108103614e2657634e487b7160e01b600052602260045260246000fd5b50919050565b602080825260039082015262454f4160e81b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561094157610941614e9a565b6000815160c08452614ed860c0850182614454565b905060208301518482036020860152614ef18282614454565b91505060408301518482036040860152614f0b8282614454565b91505060608301518482036060860152614f258282614454565b9150506080830151608085015260a083015160a08501528091505092915050565b604081526000614f596040830185614ec3565b8281036020840152614f6b8185614ec3565b95945050505050565b602080825260089082015267195c5d5a5c1c195960c21b604082015260600190565b600060208284031215614fa857600080fd5b815161402b81614a39565b6020808252600690820152651c185d5cd95960d21b604082015260600190565b600060208284031215614fe557600080fd5b815161402b81614403565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b8381526020810183905281516001600160a01b031660408201526101e0810160208301516001600160a01b0381166060840152506040830151608083015260608301516001600160a01b03811660a084015250608083015160c083015260a083015160e083015260c0830151610100818185015260e0850151915061012082818601528186015161014086015280860151925050506150d7610160840182805182526020810151602083015260408101516040830152606081015160608301525050565b50949350505050565b634e487b7160e01b600052603260045260246000fd5b8082018082111561094157610941614e9a565b601f821115610b83576000816000526020600020601f850160051c810160208610156151325750805b601f850160051c820191505b818110156151515782815560010161513e565b505050505050565b81516001600160401b0381111561517257615172614536565b615186816151808454614df2565b84615109565b602080601f8311600181146151bb57600084156151a35750858301515b600019600386901b1c1916600185901b178555615151565b600085815260208120601f198616915b828110156151ea578886015182559484019460019091019084016151cb565b50858210156152085787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061522b6040830185614391565b90508260208301529392505050565b6020815260018060a01b038251166020820152602082015160408201526000604083015160a0606084015261527260c0840182614454565b90506060840151151560808401526080840151151560a08401528091505092915050565b82815260406020820152600061278c6040830184614391565b60c0815260008351606060c08401526152cc610120840182614454565b905060208086015160bf19808685030160e08701526152eb8483614454565b604089015187820390920161010088015281518082529184019450600092508301905b808310156153305784511515825293830193600192909201919083019061530e565b50935061536c90508482018680518252602081015160208301526040810151604083015260608101516060830152608081015160808301525050565b50509392505050565b60006020828403121561538757600080fd5b5051919050565b6000826153ab57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b038681168252858116602083015260a0820190600386106153da576153da614506565b8560408401528085166060840152508260808301529695505050505050565b60408152600061522b6040830185614454565b600081548084526020808501945083600052602060002060005b8381101561448557815487529582019560019182019101615426565b60c08252600061545560c084018361540c565b838103602085015261546a816001850161540c565b90508381036040850152615481816002850161540c565b90508381036060850152615498816003850161540c565b6004840154608086015260059093015460a09094019390935250919050565b60018060a01b03851681528360208201526080604082015260006154de6080830185615442565b905082606083015295945050505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061557490830184614391565b9695505050505050565b60006020828403121561559057600080fd5b815161402b8161435e565b60006020808352606080828501526155b6608085018661540c565b6001601f196040818885030160408901526155d384848b0161540c565b888103929092016060890152600289018054808452600091825260208083209650909301925b80601f8301101561585c57855460ff808216151586526156218a8701828460081c1615159052565b615633858701828460101c1615159052565b615645898701828460181c1615159052565b818a1c81161515608087015260a0615665818801838560281c1615159052565b60c0615679818901848660301c1615159052565b60e061568d818a01858760381c1615159052565b84881c841615156101008a01526156ae6101208a01858760481c1615159052565b6156c26101408a01858760501c1615159052565b6156d66101608a01858760581c1615159052565b848c1c841615156101808a01526156f76101a08a01858760681c1615159052565b61570b6101c08a01858760701c1615159052565b61571f6101e08a01858760781c1615159052565b6157336102008a01858760801c1615159052565b6157476102208a01858760881c1615159052565b61575b6102408a01858760901c1615159052565b61576f6102608a01858760981c1615159052565b84831c841615156102808a01526157906102a08a01858760a81c1615159052565b6157a46102c08a01858760b01c1615159052565b6157b86102e08a01858760b81c1615159052565b84821c841615156103008a01526157d96103208a01858760c81c1615159052565b6157ed6103408a01858760d01c1615159052565b6158016103608a01858760d81c1615159052565b84901c83161515610380890152505060e882901c811615156103a08701526158336103c08701828460f01c1615159052565b506158466103e086018260f81c15159052565b50948401946104009390930192908701906155f9565b85549650808210156158795760ff87161515845292870192908401905b8082101561589b576158928460ff8960081c1615159052565b92870192908401905b808210156158bd576158b48460ff8960101c1615159052565b92870192908401905b808210156158df576158d68460ff8960181c1615159052565b92870192908401905b808210156158fa5786881c60ff161515845292870192908401905b8082101561591c576159138460ff8960281c1615159052565b92870192908401905b8082101561593e576159358460ff8960301c1615159052565b92870192908401905b80821015615960576159578460ff8960381c1615159052565b92870192908401905b80821015615982576159798460ff8960401c1615159052565b92870192908401905b808210156159a45761599b8460ff8960481c1615159052565b92870192908401905b808210156159c6576159bd8460ff8960501c1615159052565b92870192908401905b808210156159e8576159df8460ff8960581c1615159052565b92870192908401905b80821015615a0a57615a018460ff8960601c1615159052565b92870192908401905b80821015615a2c57615a238460ff8960681c1615159052565b92870192908401905b80821015615a4e57615a458460ff8960701c1615159052565b92870192908401905b80821015615a7057615a678460ff8960781c1615159052565b92870192908401905b80821015615a9257615a898460ff8960801c1615159052565b92870192908401905b80821015615ab457615aab8460ff8960881c1615159052565b92870192908401905b80821015615ad657615acd8460ff8960901c1615159052565b92870192908401905b80821015615af857615aef8460ff8960981c1615159052565b92870192908401905b80821015615b1a57615b118460ff8960a01c1615159052565b92870192908401905b80821015615b3c57615b338460ff8960a81c1615159052565b92870192908401905b80821015615b5e57615b558460ff8960b01c1615159052565b92870192908401905b80821015615b8057615b778460ff8960b81c1615159052565b92870192908401905b80821015615ba257615b998460ff8960c01c1615159052565b92870192908401905b80821015615bc457615bbb8460ff8960c81c1615159052565b92870192908401905b80821015615be657615bdd8460ff8960d01c1615159052565b92870192908401905b80821015615c0857615bff8460ff8960d81c1615159052565b92870192908401905b80821015615c2a57615c218460ff8960e01c1615159052565b92870192908401905b80821015615c4c57615c438460ff8960e81c1615159052565b92870192908401905b80821015615c6e57615c658460ff8960f01c1615159052565b92870192908401905b80821015615c8957615c84848860f81c15159052565b928701925b50919998505050505050505050565b600082601f830112615ca957600080fd5b81516020615cb961460a836145c6565b8083825260208201915060208460051b870101935086841115615cdb57600080fd5b602086015b8481101561464d5780518352918301918301615ce0565b600060c08284031215615d0957600080fd5b615d1161454c565b905081516001600160401b0380821115615d2a57600080fd5b615d3685838601615c98565b83526020840151915080821115615d4c57600080fd5b615d5885838601615c98565b60208401526040840151915080821115615d7157600080fd5b615d7d85838601615c98565b60408401526060840151915080821115615d9657600080fd5b50615da384828501615c98565b6060830152506080820151608082015260a082015160a082015292915050565b60008060408385031215615dd657600080fd5b82516001600160401b0380821115615ded57600080fd5b615df986838701615cf7565b93506020850151915080821115615e0f57600080fd5b50614ba385828601615cf7565b60408152600061522b6040830185614ec3565b600080600060608486031215615e4457600080fd5b83516001600160401b0380821115615e5b57600080fd5b615e6787838801615c98565b94506020860151915080821115615e7d57600080fd5b50615e8a86828701615c98565b925050604084015160068110615e9f57600080fd5b809150509250925092565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220c7637622787df9ce503483ee2d3ac40d79b6b54d50f45c00a7de8df04c48540164736f6c63430008170033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104075760003560e01c80636c0360eb11610220578063b423799e11610130578063d909ea5f116100b8578063f020c59411610087578063f020c594146108b3578063f5470d7b146108f3578063f77c4791146108fc578063fcc78fa514610904578063ffa1ad741461072157600080fd5b8063d909ea5f146108b3578063dee1f0e4146108ba578063e327a6af146108cd578063e985e9c5146108e057600080fd5b8063b9114ce1116100ff578063b9114ce114610854578063bc0d396b14610867578063c87b56dd1461087a578063d1089f331461088d578063d1730f1f146108a057600080fd5b8063b423799e14610805578063b429afeb14610825578063b75f4d8f14610838578063b88d4fde1461084157600080fd5b80639845f17a116101b3578063a0bcfc7f11610182578063a0bcfc7f1461078e578063a0fe0f51146107a1578063a22cb465146107b4578063a5d3bafb146107c7578063a60138a7146107f257600080fd5b80639845f17a1461074d5780639d0bcca0146107605780639d118770146107685780639e2cfb0f1461077b57600080fd5b8063820e5865116101ef578063820e5865146106ec5780638e776f9c1461070e578063936725ec1461072157806395d89b411461074557600080fd5b80636c0360eb146106a957806370a08231146106b1578063718df8fa146106c45780637cc96380146106e457600080fd5b806336c944851161031b5780634f558e79116102ae578063583eab451161027d578063583eab451461063b5780636352211e1461065b57806364f2d7531461066e57806366679a0614610683578063681641381461069657600080fd5b80634f558e79146105ef5780634f6ccce7146106025780634fac6ccd14610615578063572b6c051461062857600080fd5b80633e3008b6116102ea5780633e3008b6146105c157806342842e0e146105d45780634593144c146105e75780634dd8481d1461055e57600080fd5b806336c94485146105895780633710c70a1461059c5780633c97cf60146105af5780633d54e23b146105b857600080fd5b80631f2a5ace1161039e5780632f745c591161036d5780632f745c5914610543578063325a19f11461055657806332d671a11461055e57806335320ba21461058257806335798ed01461058257600080fd5b80631f2a5ace146104ea578063203e597c1461050e57806323b872dd146105215780632e2da5171461053457600080fd5b80631249c58b116103da5780631249c58b1461048957806318160ddd1461049f5780631a8abe9a146104a75780631c001d77146104ca57600080fd5b806301ffc9a71461040c57806306fdde0314610434578063081812fc14610449578063095ea7b314610474575b600080fd5b61041f61041a366004614374565b61091c565b60405190151581526020015b60405180910390f35b61043c610947565b60405161042b91906143d7565b61045c6104573660046143ea565b6109d9565b6040516001600160a01b03909116815260200161042b565b610487610482366004614428565b610a66565b005b610491610b88565b60405190815260200161042b565b603554610491565b61041f6104b53660046143ea565b609f6020526000908152604090205460ff1681565b6104dd6104d83660046143ea565b610b9f565b60405161042b9190614490565b61043c60405180604001604052806005815260200164312e302e3360d81b81525081565b61048761051c3660046144a3565b610bb9565b61048761052f3660046144c5565b610c33565b600460405161042b919061451c565b610491610551366004614428565b610c6b565b610491610d01565b61043c60405180604001604052806005815260200164312e302e3160d81b81525081565b600161041f565b610487610597366004614724565b610d35565b6104dd6105aa3660046143ea565b610f5a565b61049160985481565b61049160995481565b6104876105cf3660046147b3565b610f74565b6104876105e23660046144c5565b6112b7565b6104916112d2565b61041f6105fd3660046143ea565b611302565b6104916106103660046143ea565b61130d565b6104876106233660046147f0565b6113a0565b61041f6106363660046147f0565b6114d3565b6104916106493660046143ea565b609e6020526000908152604090205481565b61045c6106693660046143ea565b6114f5565b610676611510565b60405161042b919061480d565b6104876106913660046148be565b611568565b6104876106a4366004614995565b6115d3565b61043c611625565b6104916106bf3660046147f0565b61162f565b6104916106d23660046143ea565b60a26020526000908152604090205481565b6104916116b6565b6106ff6106fa3660046143ea565b6116e6565b60405161042b939291906149d9565b61048761071c366004614a47565b61179f565b61043c604051806040016040528060058152602001640312e302e360dc1b81525081565b61043c611b74565b61048761075b366004614aae565b611b83565b61045c611ff7565b6104876107763660046143ea565b612027565b6104876107893660046143ea565b6121ef565b61048761079c366004614ad5565b612233565b6104876107af3660046147f0565b612277565b6104876107c2366004614b09565b61239c565b6104916107d5366004614b42565b60b460209081526000928352604080842090915290825290205481565b610487610800366004614b67565b6123ae565b6104916108133660046143ea565b60a06020526000908152604090205481565b61041f6108333660046147f0565b612400565b610491609b5481565b61048761084f366004614bad565b612425565b610487610862366004614c9b565b61245e565b6104916108753660046144a3565b61251b565b61043c6108883660046143ea565b612683565b61048761089b3660046144a3565b612794565b6104916108ae3660046143ea565b6129ce565b600061041f565b61041f6108c83660046147f0565b612ac3565b61041f6108db366004614428565b612b48565b61041f6108ee366004614dc4565b612b6e565b610491609a5481565b61045c612b9c565b60975461045c9061010090046001600160a01b031681565b60006001600160e01b0319821663780e9d6360e01b1480610941575061094182612bcc565b92915050565b60606001805461095690614df2565b80601f016020809104026020016040519081016040528092919081815260200182805461098290614df2565b80156109cf5780601f106109a4576101008083540402835291602001916109cf565b820191906000526020600020905b8154815290600101906020018083116109b257829003601f168201915b5050505050905090565b60006109e482612c1c565b610a4a5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600560205260409020546001600160a01b031690565b6000610a71826114f5565b9050806001600160a01b0316836001600160a01b031603610ade5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610a41565b806001600160a01b0316610af0612c39565b6001600160a01b03161480610b0c5750610b0c816108ee612c39565b610b795760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776044820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b6064820152608401610a41565b610b838383612c5b565b505050565b6000610b92612cc9565b610b9a612d74565b905090565b6000818152609c6020526040902060609061094190612f87565b610bc1613016565b610bdd5760405162461bcd60e51b8152600401610a4190614e2c565b610be68261302e565b610bef8161302e565b60405162461bcd60e51b815260206004820152600a602482015269636f6e73756d61626c6560b01b6044820152606401610a41565b60405180910390a15b50505050565b610c44610c3e612c39565b826130aa565b610c605760405162461bcd60e51b8152600401610a4190614e49565b610b8383838361316c565b6000610c768361162f565b8210610cd85760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610a41565b506001600160a01b03919091166000908152603360209081526040808320938352929052205490565b6000610b9a610d3160017f6f55f470bdc9cb5f04223fd822021061668e4dccb43e8727b295106dc9769c8b614eb0565b5490565b610d3d613313565b6002876080015110610d7d5760405162461bcd60e51b81526020600482015260096024820152683bb937b7339036b4b760b91b6044820152606401610a41565b86518051889160a391610d97918391602090910190614262565b506020828101518051610db09260018501920190614262565b5060408201518051610dcc916002840191602090910190614262565b5060608201518051610de8916003840191602090910190614262565b506080820151600482015560a09091015160059091015585518051879160a991610e19918391602090910190614262565b506020828101518051610e329260018501920190614262565b5060408201518051610e4e916002840191602090910190614262565b5060608201518051610e6a916003840191602090910190614262565b50608082810151600483015560a0909201516005909101556040805180830182528781526020808201889052818301879052606091820186905260af89905560b088905560b187905560b286905560b38590556097805460ff191660011790558251938401835288845283018790528282018690528201849052517f602b6148a680b6852202136cd0ed63398bb67e9b54ab8248ddcf8cc87928c24991610f109161480d565b60405180910390a17f7dc32c0d4744428a5321dfa2ba3882a2f7506b6484e465132ecabd335cdb29798787604051610f49929190614f46565b60405180910390a150505050505050565b6000818152609d6020526040902060609061094190612f87565b6000610f7e612b9c565b9050610f898561302e565b610f91613016565b610fad5760405162461bcd60e51b8152600401610a4190614e2c565b6000858152609f602052604090205460ff1615610fdc5760405162461bcd60e51b8152600401610a4190614f74565b806001600160a01b03166318d928316040518163ffffffff1660e01b8152600401602060405180830381865afa15801561101a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103e9190614f96565b1561105b5760405162461bcd60e51b8152600401610a4190614fb3565b60006001600160a01b0316846001600160a01b03166396336b306040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110c89190614fd3565b6001600160a01b0316036110ee5760405162461bcd60e51b8152600401610a4190614ff0565b7300379dd90b2a337c4652e286e4fbceadef940a21634c5ab701609c609d604051806101400160405280611120612c39565b6001600160a01b03168152602001866001600160a01b031681526020018a8152602001896001600160a01b03168152602001888152602001878152602001609a548152602001609b54815260200160a260008c815260200190815260200160002054815260200160af6040518060800160405290816000820154815260200160018201548152602001600282015481526020016003820154815250508152506040518463ffffffff1660e01b81526004016111dd93929190615013565b60006040518083038186803b1580156111f557600080fd5b505af4158015611209573d6000803e3d6000fd5b5050505061122f611218612c39565b8587604051806020016040528060008152506133bd565b6000858152609f60209081526040808320805460ff1916600117905560b482528083206001600160a01b03881680855290835292819020869055805188815291820192909252908101849052606081018390527f3be07f3d969f411bb95cc5b5af0235965db26ca648e7df2d84a0424d0086aabf906080015b60405180910390a15050505050565b610b8383838360405180602001604052806000815250612425565b6000610b9a610d3160017f812a673dfca07956350df10f8a654925f561d7a0da09bdbe79e653939a14d9f1614eb0565b600061094182612c1c565b600061131860355490565b821061137b5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610a41565b6035828154811061138e5761138e6150e0565b90600052602060002001549050919050565b3330146113ef5760405162461bcd60e51b815260206004820152601b60248201527f496e637265617365207265766973696f6e20666f7262696464656e00000000006044820152606401610a41565b600061141f610d3160017f22573091f17911fb166032a3d9e0554aa73d31b7b7ddea4a4dd2995650af84bd614eb0565b61142a9060016150f6565b905061145e8161145b60017f22573091f17911fb166032a3d9e0554aa73d31b7b7ddea4a4dd2995650af84bd614eb0565b55565b61148d8261145b60017fbfaaa2fb63266ff27c2da975f5894955056f50419af651a81f6c5060581857e4614eb0565b604080518281526001600160a01b03841660208201527ff27e2ef832a4eb8ed8ec553b875eecd44764cda95b1c24170e281539e0a869c891015b60405180910390a15050565b6001600160a01b031673d8253782c45a12053594b9deb72d8e8ab2fca54c1490565b6000908152600360205260409020546001600160a01b031690565b61153b6040518060800160405280600081526020016000815260200160008152602001600081525090565b506040805160808101825260af54815260b054602082015260b1549181019190915260b254606082015290565b6115706133f0565b61157c88888b89613469565b60978054610100600160a81b0319166101006001600160a01b038816021790556098849055609983905581600b8111156115b8576115b8614506565b609a55609b8190556115c86134c5565b505050505050505050565b6115db613313565b600081815260a1602052604090206115f38382615159565b507f29f443087b03c724ded11254c74c7211dcb5e505b280d10747d67f3a0227879082826040516114c7929190615218565b6060610b9a6134e1565b60006001600160a01b03821661169a5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610a41565b506001600160a01b031660009081526004602052604090205490565b6000610b9a610d3160017f22573091f17911fb166032a3d9e0554aa73d31b7b7ddea4a4dd2995650af84bd614eb0565b60608061171b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b600084815260da6020526040902061173290612f87565b600085815260db6020526040902061174990612f87565b600095865260dc6020908152604096879020875160a08101895281548152600182015492810192909252600281015497820197909752600387015460608201526004909601546080870152909590949350915050565b60006117a9612b9c565b90506117b4816134f0565b6000878152609f602052604090205460ff1680156117f35750600087815260b4602090815260408083206001600160a01b038a16845290915290205485145b61182b5760405162461bcd60e51b815260206004820152600960248201526808595c5d5a5c1c195960ba1b6044820152606401610a41565b609a54600081900361186c5760405162461bcd60e51b815260206004820152600a602482015269636f6e73756d61626c6560b01b6044820152606401610a41565b6000826001600160a01b0316628e96916040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cf9190614fd3565b604051630c6222cb60e01b81526001600160a01b038a81166004830152602482018a9052604482018590526064820189905230608483015260a482018c9052600060c483015291925090821690630c6222cb9060e401600060405180830381600087803b15801561193f57600080fd5b505af1158015611953573d6000803e3d6000fd5b50505050831561196d57600089815260a260205260408120555b806001600160a01b03166324a0b0356040518060a001604052808b6001600160a01b031681526020018a81526020016119b7609c60008f8152602001908152602001600020612f87565b8152600060208201819052604091820152516001600160e01b031960e084901b1681526119e7919060040161523a565b600060405180830381600087803b158015611a0157600080fd5b505af1158015611a15573d6000803e3d6000fd5b50505050806001600160a01b03166324a0b0356040518060a001604052808b6001600160a01b031681526020018a8152602001611a63609d60008f8152602001908152602001600020612f87565b8152600160208201526000604091820152516001600160e01b031960e084901b168152611a93919060040161523a565b600060405180830381600087803b158015611aad57600080fd5b505af1158015611ac1573d6000803e3d6000fd5b50505060008a8152609f60209081526040808320805460ff1916905560b482528083206001600160a01b038d168452825280832083905580519182019052908152611b129150899087908c906133bd565b604080518a81526001600160a01b038a811660208301528183018a9052606082018990528716608082015290517fc64e9512c33531b1b4767eb306c4690a87eb36bc541a383fa538499648e9a9f49181900360a00190a1505050505050505050565b60606002805461095690614df2565b6000611b8d612b9c565b9050611b988461302e565b611ba0613016565b611bbc5760405162461bcd60e51b8152600401610a4190614e2c565b806001600160a01b03166318d928316040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c1e9190614f96565b15611c3b5760405162461bcd60e51b8152600401610a4190614fb3565b6000816001600160a01b0316628e96916040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9e9190614fd3565b60405163223e40cf60e01b81526001600160a01b038083166004830152861660248201526044810185905260af54606482015260b054608482015260b15460a482015260b25460c48201529091507300379dd90b2a337c4652e286e4fbceadef940a219063223e40cf9060e40160006040518083038186803b158015611d2357600080fd5b505af4158015611d37573d6000803e3d6000fd5b505060405163138e914f60e11b81526001600160a01b038781166004830152602482018790523060448301528416925063271d229e9150606401600060405180830381600087803b158015611d8b57600080fd5b505af1158015611d9f573d6000803e3d6000fd5b505050600086815260dc60205260409081902090516381b182cd60e01b81526001600160a01b038781166004808401919091526024830188905283546044840152600180850154606485015260028501546084850152600385015460a485015293015460c483015260e482019290925290831691506381b182cd9061010401600060405180830381600087803b158015611e3857600080fd5b505af1158015611e4c573d6000803e3d6000fd5b50505050806001600160a01b03166324a0b0356040518060a00160405280876001600160a01b03168152602001868152602001611e9a60da60008b8152602001908152602001600020612f87565b8152600160208201819052604091820152516001600160e01b031960e084901b168152611eca919060040161523a565b600060405180830381600087803b158015611ee457600080fd5b505af1158015611ef8573d6000803e3d6000fd5b50505050806001600160a01b03166324a0b0356040518060a00160405280876001600160a01b03168152602001868152602001611f4660db60008b8152602001908152602001600020612f87565b8152600060208201526001604091820152516001600160e01b031960e084901b168152611f76919060040161523a565b600060405180830381600087803b158015611f9057600080fd5b505af1158015611fa4573d6000803e3d6000fd5b50505050611fb185613071565b604080518681526001600160a01b03861660208201529081018490527f8f0c0d91ba98d7745b984165ac65d4e188c2455ccc13d5155c860f0d9246a815906060016112a8565b6000610b9a610d3160017fbfaaa2fb63266ff27c2da975f5894955056f50419af651a81f6c5060581857e4614eb0565b6000612031612b9c565b9050806001600160a01b03166325a6c51d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612071573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120959190614fd3565b60405163f2f4a8af60e01b81523360048201526001600160a01b03919091169063f2f4a8af90602401602060405180830381865afa1580156120db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ff9190614f96565b8061217c5750336001600160a01b0316816001600160a01b031663524a562f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561214d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121719190614fd3565b6001600160a01b0316145b8061219757503361218c836114f5565b6001600160a01b0316145b6121b35760405162461bcd60e51b8152600401610a4190614ff0565b6000828152609f602052604090205460ff16156121e25760405162461bcd60e51b8152600401610a4190614f74565b6121eb82613071565b5050565b6121f7613313565b609b8190556040518181527f7ef6d608ec96a3c1d48de6ceb0c0bd19618f4b93f0095308c79cd6ca4b51b187906020015b60405180910390a150565b61223b613313565b60666122478282615159565b507f87cdeaffd8e70903d6ce7cc983fac3b09ca79e83818124c98e47a1d70f8027d68160405161222891906143d7565b61227f6135e6565b6001600160a01b0381166122c75760405162461bcd60e51b815260206004820152600f60248201526e2d32b9379031b7b73a3937b63632b960891b6044820152606401610a41565b6122f68161145b60017f5165972ef41194f06c5007493031d0b927c20741adcb74403b954009fd2c3618614eb0565b6123254261145b60017f6f55f470bdc9cb5f04223fd822021061668e4dccb43e8727b295106dc9769c8b614eb0565b6123544361145b60017f812a673dfca07956350df10f8a654925f561d7a0da09bdbe79e653939a14d9f1614eb0565b604080516001600160a01b038316815242602082015243918101919091527f1a2dd071001ebf6e03174e3df5b305795a4ad5d41d8fdb9ba41dbbe23671342690606001612228565b6121eb6123a7612c39565b838361362c565b6123b6613313565b60008281526067602052604090206123ce8282615159565b507ff32b5bcd021361ac825fde09ff2121b0e5783f9f993196194fab9471799e54dd82826040516114c7929190615296565b600061240a612b9c565b6001600160a01b0316826001600160a01b0316149050919050565b612436612430612c39565b836130aa565b6124525760405162461bcd60e51b8152600401610a4190614e49565b610c2d848484846133bd565b612466613313565b81518051839160dd91612480918391602090910190614262565b5060208281015180516124999260018501920190614262565b50604082015180516124b59160028401916020909101906142ad565b5050815160e05550602081015160e15560408082015160e255606082015160e355608082015160e45560d9805460ff19166001179055517fc8e30ad432142bd0dfb602223be2c9714576cc124dbcee021719e2f29cdaf0b5906114c790849084906152af565b600080612526612b9c565b9050612531816134f0565b6000816001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612571573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125959190614fd3565b600086815260a2602052604080822054609954609a54925163b3e13ad160e01b8152600481018a9052602481019290925260448201526064810191909152919250906001600160a01b0383169063b3e13ad190608401602060405180830381865afa158015612608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262c9190615375565b600087815260a2602090815260409182902083905581518981529081018390529192507feb46efb0c7198679c79853a979eb80da18892986f9942ca8873ed7c4cefb5975910160405180910390a195945050505050565b60606065548211156126c05760405162461bcd60e51b815260206004820152600660248201526508595e1a5cdd60d21b6044820152606401610a41565b600082815260676020526040812080546126d990614df2565b80601f016020809104026020016040519081016040528092919081815260200182805461270590614df2565b80156127525780601f1061272757610100808354040283529160200191612752565b820191906000526020600020905b81548152906001019060200180831161273557829003601f168201915b5050505050905080516000146127685792915050565b6000612773846136fa565b805190915015612784579392505050565b61278c6134e1565b949350505050565b600061279e612b9c565b90506127a8613016565b6127c45760405162461bcd60e51b8152600401610a4190614e2c565b6127cd8361302e565b6127d68261302e565b609b5460008190036128185760405162461bcd60e51b815260206004820152600b60248201526a216475726162696c69747960a81b6044820152606401610a41565b6000848152609f602052604090205460ff1615801561284657506000838152609f602052604090205460ff16155b6128625760405162461bcd60e51b8152600401610a4190614f74565b816001600160a01b03166318d928316040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c49190614f96565b156128e15760405162461bcd60e51b8152600401610a4190614fb3565b6128ea83613071565b7300379dd90b2a337c4652e286e4fbceadef940a2163806f099d61290c612b9c565b60975461010090046001600160a01b03166001612927612c39565b600a609854612936919061538e565b6040518663ffffffff1660e01b81526004016129569594939291906153b0565b60006040518083038186803b15801561296e57600080fd5b505af4158015612982573d6000803e3d6000fd5b505050600085815260a2602090815260409182902084905581518781529081018690527ffc4ee3fbea4df52f867d98cb796e03a5ae97157fa0c2372c6f61d4336543a7ee925001610c24565b60006129d8612b9c565b6001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190614fd3565b6001600160a01b03166351c9120d612a62609c6000868152602001908152602001600020612f87565b609b546040518363ffffffff1660e01b8152600401612a829291906153f9565b602060405180830381865afa158015612a9f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109419190615375565b6000816001600160a01b0316612ad7612b9c565b6001600160a01b0316635aa6e6756040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b389190614fd3565b6001600160a01b03161492915050565b6000826001600160a01b0316612b5d836114f5565b6001600160a01b0316149392505050565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205460ff1690565b6000610b9a610d3160017f5165972ef41194f06c5007493031d0b927c20741adcb74403b954009fd2c3618614eb0565b60006001600160e01b031982166380ac58cd60e01b1480612bfd57506001600160e01b03198216635b5e139f60e01b145b8061094157506301ffc9a760e01b6001600160e01b0319831614610941565b6000908152600360205260409020546001600160a01b0316151590565b6000612c44336114d3565b15612c56575060131936013560601c90565b503390565b600081815260056020526040902080546001600160a01b0319166001600160a01b0384169081179091558190612c90826114f5565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b612cd1612b9c565b604051633ec963c960e01b81523360048201526001600160a01b039190911690633ec963c990602401602060405180830381865afa158015612d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3b9190614f96565b612d725760405162461bcd60e51b815260206004820152600860248201526710b23ab733b2b7b760c11b6044820152606401610a41565b565b6000612d7e6137a9565b9050612d91612d8b612c39565b826137c2565b6000612d9b612b9c565b6001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015612dd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dfc9190614fd3565b6000838152609c602052604080822060b354915163fe1a90f160e01b815293945091927300379dd90b2a337c4652e286e4fbceadef940a219263fe1a90f192612e4d9287929160a3916004016154b7565b602060405180830381865af4158015612e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e8e9190615375565b6000848152609d602052604090819020905163fe1a90f160e01b81529192507300379dd90b2a337c4652e286e4fbceadef940a219163fe1a90f191612ede9186919060a9906001906004016154b7565b602060405180830381865af4158015612efb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1f9190615375565b506000838152609e60209081526040808320849055609b5460a290925290912055612f49836137dc565b60408051848152602081018390527f8a9dcf4e150b1153011b29fec302d5be0c13e84fa8f56ab78587f778a32a90dd910160405180910390a1505090565b60606000612f948361383e565b60408051602b808252610580820190925291925060009190602082016105608036833701905050905060005b8281101561300e57600080612fd58784613849565b915091506000811215612fe6575060005b80848381518110612ff957612ff96150e0565b60209081029190910101525050600101612fc0565b509392505050565b6000613021336114d3565b80610b9a57505032331490565b613036612c39565b6001600160a01b0316613048826114f5565b6001600160a01b03161461306e5760405162461bcd60e51b8152600401610a4190614ff0565b50565b61307a81613865565b6040518181527ff15a2816d9b33bd70f4b57d8cfbd7ee75d3231d8c52a030fef8a86fb4adfe94790602001612228565b60006130b582612c1c565b6131165760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a41565b6000613121836114f5565b9050806001600160a01b0316846001600160a01b0316148061315c5750836001600160a01b0316613151846109d9565b6001600160a01b0316145b8061278c575061278c8185612b6e565b826001600160a01b031661317f826114f5565b6001600160a01b0316146131e35760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610a41565b6001600160a01b0382166132455760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610a41565b61325083838361390c565b61325b600082612c5b565b6001600160a01b0383166000908152600460205260408120805460019290613284908490614eb0565b90915550506001600160a01b03821660009081526004602052604081208054600192906132b29084906150f6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b61331b612b9c565b604051631430d62960e21b81523360048201526001600160a01b0391909116906350c358a490602401602060405180830381865afa158015613361573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133859190614f96565b612d725760405162461bcd60e51b815260206004820152600960248201526810b232b83637bcb2b960b91b6044820152606401610a41565b6133c884848461316c565b6133d484848484613946565b610c2d5760405162461bcd60e51b8152600401610a41906154ef565b600054610100900460ff1661340b5760005460ff161561340f565b303b155b6134495760405162461bcd60e51b815260206004820152600b60248201526a1a5b9a5d1a585b1a5e995960aa1b6044820152606401610a41565b600054610100900460ff16612d72576000805461ffff1916610101179055565b6134716135e6565b61347b8484613a4e565b61348482612277565b600160655560666134958282615159565b507f87cdeaffd8e70903d6ce7cc983fac3b09ca79e83818124c98e47a1d70f8027d681604051610c2491906143d7565b600054610100900460ff16612d72576000805461ff0019169055565b60606066805461095690614df2565b60405163ba79bf5f60e01b81523360048201526001600160a01b0382169063ba79bf5f90602401602060405180830381865afa158015613534573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135589190614f96565b806135ca5750336001600160a01b0316816001600160a01b031663524a562f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156135a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130489190614fd3565b61306e5760405162461bcd60e51b8152600401610a4190614ff0565b600054610100900460ff16612d725760405162461bcd60e51b815260206004820152600c60248201526b696e697469616c697a696e6760a01b6044820152606401610a41565b816001600160a01b0316836001600160a01b03160361368d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a41565b6001600160a01b03838116600081815260066020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000818152609e6020908152604080832054835260a1909152902080546060919061372490614df2565b80601f016020809104026020016040519081016040528092919081815260200182805461375090614df2565b801561379d5780601f106137725761010080835404028352916020019161379d565b820191906000526020600020905b81548152906001019060200180831161378057829003601f168201915b50505050509050919050565b6065546000906137ba8160016150f6565b606555919050565b6121eb828260405180602001604052806000815250613a60565b600081815260da6020908152604080832060db909252909120613800919083613a93565b600091825260dc6020908152604092839020825181559082015160018201559181015160028301556060810151600383015560800151600490910155565b600061094182613dba565b60008080806138588686613dc5565b9097909650945050505050565b6000613870826114f5565b905061387e8160008461390c565b613889600083612c5b565b6001600160a01b03811660009081526004602052604081208054600192906138b2908490614eb0565b909155505060008281526003602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6000818152609f602052604090205460ff161561393b5760405162461bcd60e51b8152600401610a4190614f74565b610b83838383613df0565b60006001600160a01b0384163b15613a4357836001600160a01b031663150b7a0261396f612c39565b8786866040518563ffffffff1660e01b81526004016139919493929190615541565b6020604051808303816000875af19250505080156139cc575060408051601f3d908101601f191682019092526139c99181019061557e565b60015b613a29573d8080156139fa576040519150601f19603f3d011682016040523d82523d6000602084013e6139ff565b606091505b508051600003613a215760405162461bcd60e51b8152600401610a41906154ef565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061278c565b506001949350505050565b613a566135e6565b6121eb8282613ea8565b613a6a8383613ec9565b613a776000848484613946565b610b835760405162461bcd60e51b8152600401610a41906154ef565b613ac56040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6000613acf612b9c565b6001600160a01b031663fcad8c786040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b309190614fd3565b9050600080826001600160a01b0316635cb8980f60dd6040518263ffffffff1660e01b8152600401613b62919061559b565b600060405180830381865afa158015613b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613ba79190810190615dc3565b91509150600080846001600160a01b0316635027f3848560b3546040518363ffffffff1660e01b8152600401613bde929190615e1c565b6000604051808303816000875af1158015613bfd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c259190810190615e2f565b509150915060005b8151811015613c91576000828281518110613c4a57613c4a6150e0565b602002602001015190506000848381518110613c6857613c686150e0565b6020026020010151905081600014613c8757613c858c8284614008565b505b5050600101613c2d565b5060b354604051631409fce160e21b815260009182916001600160a01b03891691635027f38491613cc6918991600401615e1c565b6000604051808303816000875af1158015613ce5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d0d9190810190615e2f565b509150915060005b8151811015613d79576000828281518110613d3257613d326150e0565b602002602001015190506000848381518110613d5057613d506150e0565b6020026020010151905081600014613d6f57613d6d8d8284614008565b505b5050600101613d15565b50506040805160a08101825260e054815260e154602082015260e2549181019190915260e354606082015260e45460808201529a9950505050505050505050565b600061094182614015565b60008080613dd3858561401f565b600081815260029690960160205260409095205494959350505050565b6001600160a01b038316613e4b57613e4681603580546000838152603660205260408120829055600182018355919091527fcfa4bec1d3298408bb5afcfcd9c430549c5b31f8aa5c5848151c0a55f473c34d0155565b613e6e565b816001600160a01b0316836001600160a01b031614613e6e57613e6e8382614032565b6001600160a01b038216613e8557610b83816140cf565b826001600160a01b0316826001600160a01b031614610b8357610b83828261417e565b613eb06135e6565b6001613ebc8382615159565b506002610b838282615159565b6001600160a01b038216613f1f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a41565b613f2881612c1c565b15613f755760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a41565b613f816000838361390c565b6001600160a01b0382166000908152600460205260408120805460019290613faa9084906150f6565b909155505060008181526003602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600061278c8484846141c2565b6000610941825490565b600061402b83836141df565b9392505050565b6000600161403f8461162f565b6140499190614eb0565b60008381526034602052604090205490915080821461409c576001600160a01b03841660009081526033602090815260408083208584528252808320548484528184208190558352603490915290208190555b5060009182526034602090815260408084208490556001600160a01b039094168352603381528383209183525290812055565b6035546000906140e190600190614eb0565b60008381526036602052604081205460358054939450909284908110614109576141096150e0565b90600052602060002001549050806035838154811061412a5761412a6150e0565b600091825260208083209091019290925582815260369091526040808220849055858252812055603580548061416257614162615eaa565b6001900381819060005260206000200160009055905550505050565b60006141898361162f565b6001600160a01b039093166000908152603360209081526040808320868452825280832085905593825260349052919091209190915550565b6000828152600284016020526040812082905561278c8484614209565b60008260000182815481106141f6576141f66150e0565b9060005260206000200154905092915050565b600081815260018301602052604081205461402b9084908490849061425a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610941565b506000610941565b82805482825590600052602060002090810192821561429d579160200282015b8281111561429d578251825591602001919060010190614282565b506142a9929150614349565b5090565b82805482825590600052602060002090601f0160209004810192821561429d5791602002820160005b8382111561431357835183826101000a81548160ff02191690831515021790555092602001926001016020816000010492830192600103026142d6565b80156143405782816101000a81549060ff0219169055600101602081600001049283019260010302614313565b50506142a99291505b5b808211156142a9576000815560010161434a565b6001600160e01b03198116811461306e57600080fd5b60006020828403121561438657600080fd5b813561402b8161435e565b6000815180845260005b818110156143b75760208185018101518683018201520161439b565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061402b6020830184614391565b6000602082840312156143fc57600080fd5b5035919050565b6001600160a01b038116811461306e57600080fd5b803561442381614403565b919050565b6000806040838503121561443b57600080fd5b823561444681614403565b946020939093013593505050565b60008151808452602080850194506020840160005b8381101561448557815187529582019590820190600101614469565b509495945050505050565b60208152600061402b6020830184614454565b600080604083850312156144b657600080fd5b50508035926020909101359150565b6000806000606084860312156144da57600080fd5b83356144e581614403565b925060208401356144f581614403565b929592945050506040919091013590565b634e487b7160e01b600052602160045260246000fd5b602081016005831061453057614530614506565b91905290565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b038111828210171561456e5761456e614536565b60405290565b604051606081016001600160401b038111828210171561456e5761456e614536565b604051601f8201601f191681016001600160401b03811182821017156145be576145be614536565b604052919050565b60006001600160401b038211156145df576145df614536565b5060051b60200190565b600082601f8301126145fa57600080fd5b8135602061460f61460a836145c6565b614596565b8083825260208201915060208460051b87010193508684111561463157600080fd5b602086015b8481101561464d5780358352918301918301614636565b509695505050505050565b600060c0828403121561466a57600080fd5b61467261454c565b905081356001600160401b038082111561468b57600080fd5b614697858386016145e9565b835260208401359150808211156146ad57600080fd5b6146b9858386016145e9565b602084015260408401359150808211156146d257600080fd5b6146de858386016145e9565b604084015260608401359150808211156146f757600080fd5b50614704848285016145e9565b6060830152506080820135608082015260a082013560a082015292915050565b600080600080600080600060e0888a03121561473f57600080fd5b87356001600160401b038082111561475657600080fd5b6147628b838c01614658565b985060208a013591508082111561477857600080fd5b506147858a828b01614658565b979a9799505050506040860135956060810135956080820135955060a0820135945060c09091013592509050565b600080600080608085870312156147c957600080fd5b8435935060208501356147db81614403565b93969395505050506040820135916060013590565b60006020828403121561480257600080fd5b813561402b81614403565b8151815260208083015190820152604080830151908201526060808301519082015260808101610941565b60006001600160401b0383111561485157614851614536565b614864601f8401601f1916602001614596565b905082815283838301111561487857600080fd5b828260208301376000602084830101529392505050565b600082601f8301126148a057600080fd5b61402b83833560208501614838565b8035600c811061442357600080fd5b60008060008060008060008060006101208a8c0312156148dd57600080fd5b6148e68a614418565b985060208a01356001600160401b038082111561490257600080fd5b61490e8d838e0161488f565b995060408c013591508082111561492457600080fd5b6149308d838e0161488f565b985060608c013591508082111561494657600080fd5b506149538c828d0161488f565b96505061496260808b01614418565b945060a08a0135935060c08a0135925061497e60e08b016148af565b91506101008a013590509295985092959850929598565b600080604083850312156149a857600080fd5b82356001600160401b038111156149be57600080fd5b6149ca8582860161488f565b95602094909401359450505050565b60e0815260006149ec60e0830186614454565b82810360208401526149fe8186614454565b91505061278c604083018480518252602081015160208301526040810151604083015260608101516060830152608081015160808301525050565b801515811461306e57600080fd5b60008060008060008060c08789031215614a6057600080fd5b863595506020870135614a7281614403565b945060408701359350606087013592506080870135614a9081614403565b915060a0870135614aa081614a39565b809150509295509295509295565b600080600060608486031215614ac357600080fd5b8335925060208401356144f581614403565b600060208284031215614ae757600080fd5b81356001600160401b03811115614afd57600080fd5b61278c8482850161488f565b60008060408385031215614b1c57600080fd5b8235614b2781614403565b91506020830135614b3781614a39565b809150509250929050565b60008060408385031215614b5557600080fd5b823591506020830135614b3781614403565b60008060408385031215614b7a57600080fd5b8235915060208301356001600160401b03811115614b9757600080fd5b614ba38582860161488f565b9150509250929050565b60008060008060808587031215614bc357600080fd5b8435614bce81614403565b93506020850135614bde81614403565b92506040850135915060608501356001600160401b03811115614c0057600080fd5b8501601f81018713614c1157600080fd5b614c2087823560208401614838565b91505092959194509250565b600060a08284031215614c3e57600080fd5b60405160a081018181106001600160401b0382111715614c6057614c60614536565b806040525080915082358152602083013560208201526040830135604082015260608301356060820152608083013560808201525092915050565b60008060c08385031215614cae57600080fd5b82356001600160401b0380821115614cc557600080fd5b9084019060608287031215614cd957600080fd5b614ce1614574565b823582811115614cf057600080fd5b614cfc888286016145e9565b82525060208084013583811115614d1257600080fd5b614d1e898287016145e9565b8284015250604084013583811115614d3557600080fd5b80850194505087601f850112614d4a57600080fd5b83359250614d5a61460a846145c6565b83815260059390931b84018101928181019089851115614d7957600080fd5b948201945b84861015614da0578535614d9181614a39565b82529482019490820190614d7e565b8060408501525050819550614db788828901614c2c565b9450505050509250929050565b60008060408385031215614dd757600080fd5b8235614de281614403565b91506020830135614b3781614403565b600181811c90821680614e0657607f821691505b602082108103614e2657634e487b7160e01b600052602260045260246000fd5b50919050565b602080825260039082015262454f4160e81b604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b8181038181111561094157610941614e9a565b6000815160c08452614ed860c0850182614454565b905060208301518482036020860152614ef18282614454565b91505060408301518482036040860152614f0b8282614454565b91505060608301518482036060860152614f258282614454565b9150506080830151608085015260a083015160a08501528091505092915050565b604081526000614f596040830185614ec3565b8281036020840152614f6b8185614ec3565b95945050505050565b602080825260089082015267195c5d5a5c1c195960c21b604082015260600190565b600060208284031215614fa857600080fd5b815161402b81614a39565b6020808252600690820152651c185d5cd95960d21b604082015260600190565b600060208284031215614fe557600080fd5b815161402b81614403565b6020808252600990820152683337b93134b23232b760b91b604082015260600190565b8381526020810183905281516001600160a01b031660408201526101e0810160208301516001600160a01b0381166060840152506040830151608083015260608301516001600160a01b03811660a084015250608083015160c083015260a083015160e083015260c0830151610100818185015260e0850151915061012082818601528186015161014086015280860151925050506150d7610160840182805182526020810151602083015260408101516040830152606081015160608301525050565b50949350505050565b634e487b7160e01b600052603260045260246000fd5b8082018082111561094157610941614e9a565b601f821115610b83576000816000526020600020601f850160051c810160208610156151325750805b601f850160051c820191505b818110156151515782815560010161513e565b505050505050565b81516001600160401b0381111561517257615172614536565b615186816151808454614df2565b84615109565b602080601f8311600181146151bb57600084156151a35750858301515b600019600386901b1c1916600185901b178555615151565b600085815260208120601f198616915b828110156151ea578886015182559484019460019091019084016151cb565b50858210156152085787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60408152600061522b6040830185614391565b90508260208301529392505050565b6020815260018060a01b038251166020820152602082015160408201526000604083015160a0606084015261527260c0840182614454565b90506060840151151560808401526080840151151560a08401528091505092915050565b82815260406020820152600061278c6040830184614391565b60c0815260008351606060c08401526152cc610120840182614454565b905060208086015160bf19808685030160e08701526152eb8483614454565b604089015187820390920161010088015281518082529184019450600092508301905b808310156153305784511515825293830193600192909201919083019061530e565b50935061536c90508482018680518252602081015160208301526040810151604083015260608101516060830152608081015160808301525050565b50509392505050565b60006020828403121561538757600080fd5b5051919050565b6000826153ab57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b038681168252858116602083015260a0820190600386106153da576153da614506565b8560408401528085166060840152508260808301529695505050505050565b60408152600061522b6040830185614454565b600081548084526020808501945083600052602060002060005b8381101561448557815487529582019560019182019101615426565b60c08252600061545560c084018361540c565b838103602085015261546a816001850161540c565b90508381036040850152615481816002850161540c565b90508381036060850152615498816003850161540c565b6004840154608086015260059093015460a09094019390935250919050565b60018060a01b03851681528360208201526080604082015260006154de6080830185615442565b905082606083015295945050505050565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061557490830184614391565b9695505050505050565b60006020828403121561559057600080fd5b815161402b8161435e565b60006020808352606080828501526155b6608085018661540c565b6001601f196040818885030160408901526155d384848b0161540c565b888103929092016060890152600289018054808452600091825260208083209650909301925b80601f8301101561585c57855460ff808216151586526156218a8701828460081c1615159052565b615633858701828460101c1615159052565b615645898701828460181c1615159052565b818a1c81161515608087015260a0615665818801838560281c1615159052565b60c0615679818901848660301c1615159052565b60e061568d818a01858760381c1615159052565b84881c841615156101008a01526156ae6101208a01858760481c1615159052565b6156c26101408a01858760501c1615159052565b6156d66101608a01858760581c1615159052565b848c1c841615156101808a01526156f76101a08a01858760681c1615159052565b61570b6101c08a01858760701c1615159052565b61571f6101e08a01858760781c1615159052565b6157336102008a01858760801c1615159052565b6157476102208a01858760881c1615159052565b61575b6102408a01858760901c1615159052565b61576f6102608a01858760981c1615159052565b84831c841615156102808a01526157906102a08a01858760a81c1615159052565b6157a46102c08a01858760b01c1615159052565b6157b86102e08a01858760b81c1615159052565b84821c841615156103008a01526157d96103208a01858760c81c1615159052565b6157ed6103408a01858760d01c1615159052565b6158016103608a01858760d81c1615159052565b84901c83161515610380890152505060e882901c811615156103a08701526158336103c08701828460f01c1615159052565b506158466103e086018260f81c15159052565b50948401946104009390930192908701906155f9565b85549650808210156158795760ff87161515845292870192908401905b8082101561589b576158928460ff8960081c1615159052565b92870192908401905b808210156158bd576158b48460ff8960101c1615159052565b92870192908401905b808210156158df576158d68460ff8960181c1615159052565b92870192908401905b808210156158fa5786881c60ff161515845292870192908401905b8082101561591c576159138460ff8960281c1615159052565b92870192908401905b8082101561593e576159358460ff8960301c1615159052565b92870192908401905b80821015615960576159578460ff8960381c1615159052565b92870192908401905b80821015615982576159798460ff8960401c1615159052565b92870192908401905b808210156159a45761599b8460ff8960481c1615159052565b92870192908401905b808210156159c6576159bd8460ff8960501c1615159052565b92870192908401905b808210156159e8576159df8460ff8960581c1615159052565b92870192908401905b80821015615a0a57615a018460ff8960601c1615159052565b92870192908401905b80821015615a2c57615a238460ff8960681c1615159052565b92870192908401905b80821015615a4e57615a458460ff8960701c1615159052565b92870192908401905b80821015615a7057615a678460ff8960781c1615159052565b92870192908401905b80821015615a9257615a898460ff8960801c1615159052565b92870192908401905b80821015615ab457615aab8460ff8960881c1615159052565b92870192908401905b80821015615ad657615acd8460ff8960901c1615159052565b92870192908401905b80821015615af857615aef8460ff8960981c1615159052565b92870192908401905b80821015615b1a57615b118460ff8960a01c1615159052565b92870192908401905b80821015615b3c57615b338460ff8960a81c1615159052565b92870192908401905b80821015615b5e57615b558460ff8960b01c1615159052565b92870192908401905b80821015615b8057615b778460ff8960b81c1615159052565b92870192908401905b80821015615ba257615b998460ff8960c01c1615159052565b92870192908401905b80821015615bc457615bbb8460ff8960c81c1615159052565b92870192908401905b80821015615be657615bdd8460ff8960d01c1615159052565b92870192908401905b80821015615c0857615bff8460ff8960d81c1615159052565b92870192908401905b80821015615c2a57615c218460ff8960e01c1615159052565b92870192908401905b80821015615c4c57615c438460ff8960e81c1615159052565b92870192908401905b80821015615c6e57615c658460ff8960f01c1615159052565b92870192908401905b80821015615c8957615c84848860f81c15159052565b928701925b50919998505050505050505050565b600082601f830112615ca957600080fd5b81516020615cb961460a836145c6565b8083825260208201915060208460051b870101935086841115615cdb57600080fd5b602086015b8481101561464d5780518352918301918301615ce0565b600060c08284031215615d0957600080fd5b615d1161454c565b905081516001600160401b0380821115615d2a57600080fd5b615d3685838601615c98565b83526020840151915080821115615d4c57600080fd5b615d5885838601615c98565b60208401526040840151915080821115615d7157600080fd5b615d7d85838601615c98565b60408401526060840151915080821115615d9657600080fd5b50615da384828501615c98565b6060830152506080820151608082015260a082015160a082015292915050565b60008060408385031215615dd657600080fd5b82516001600160401b0380821115615ded57600080fd5b615df986838701615cf7565b93506020850151915080821115615e0f57600080fd5b50614ba385828601615cf7565b60408152600061522b6040830185614ec3565b600080600060608486031215615e4457600080fd5b83516001600160401b0380821115615e5b57600080fd5b615e6787838801615c98565b94506020860151915080821115615e7d57600080fd5b50615e8a86828701615c98565b925050604084015160068110615e9f57600080fd5b809150509250925092565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220c7637622787df9ce503483ee2d3ac40d79b6b54d50f45c00a7de8df04c48540164736f6c63430008170033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.