diff --git a/.gitignore b/.gitignore index df95eb5..6bb462d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ node_modules # hardhat cache artifacts -deployments/localhost +deployments/hardhat # NPM package-lock.json @@ -13,9 +13,12 @@ package-lock.json out forge-cache +# OpenZeppelin +.openzeppelin/unknown-*.json + # Subgraph *.wasm subgraph/build subgraph/generated subgraph/abis -subgraph/examples/query/.graphclient \ No newline at end of file +subgraph/examples/query/.graphclient diff --git a/.openzeppelin/polygon-mumbai.json b/.openzeppelin/polygon-mumbai.json new file mode 100644 index 0000000..443b79e --- /dev/null +++ b/.openzeppelin/polygon-mumbai.json @@ -0,0 +1,1596 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0xBbb1Dadf729E034d2abB055907CC62b99eAd7959", + "txHash": "0xfb7eb4a138e69092b2948c93890f910c3e9e3e185bd4b2a251a3616bb15b4e3d" + }, + "proxies": [ + { + "address": "0x84Dc9a43B3472415a406e1a14d6b94a5c289eF7F", + "txHash": "0xf58a1f72ca0894952ab6bd23a8f3f68260f5fe39b73ec21972e9303aa7c52211", + "kind": "transparent" + }, + { + "address": "0x21d7fBe220958A0F0f7cAE58780fe812EbcB3cd8", + "txHash": "0x6a5a4b2cc5f6595438f4f0304be8b7ac55e8cfefdea857738f4451de48a82066", + "kind": "transparent" + } + ], + "impls": { + "d21b7475a07b4cc45957ef589e0fac8425415ed415665871918c71426f4221f9": { + "address": "0x37D8fD9dF6006E5A47fEe8211181928766B8242D", + "txHash": "0xdab894688f3a34c952b86473941322d8334d0964ab1f6e458431f6e8a42c546e", + "layout": { + "solcVersion": "0.8.7", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "101", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "102", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + }, + { + "label": "_collectionRolesVersion", + "offset": 0, + "slot": "151", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:26" + }, + { + "label": "_collectionRoles", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:28" + }, + { + "label": "_tokenRolesVersion", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_uint256,t_struct(Counter)2774_storage)", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:30" + }, + { + "label": "_tokenRoles", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:32" + }, + { + "label": "_tokenIds", + "offset": 0, + "slot": "155", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:44" + }, + { + "label": "_apps", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_struct(App)4606_storage)", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:45" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(Roles)3895": { + "label": "enum FleekAccessControl.Roles", + "members": ["Owner", "Controller"], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)": { + "label": "mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))": { + "label": "mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))": { + "label": "mapping(uint256 => mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(App)4606_storage)": { + "label": "mapping(uint256 => struct FleekERC721.App)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Build)4611_storage)": { + "label": "mapping(uint256 => struct FleekERC721.Build)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Counter)2774_storage)": { + "label": "mapping(uint256 => struct Counters.Counter)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(App)4606_storage": { + "label": "struct FleekERC721.App", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "externalURL", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "ENS", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "currentBuild", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "builds", + "type": "t_mapping(t_uint256,t_struct(Build)4611_storage)", + "offset": 0, + "slot": "5" + } + ], + "numberOfBytes": "192" + }, + "t_struct(Build)4611_storage": { + "label": "struct FleekERC721.Build", + "members": [ + { + "label": "commitHash", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "gitRepository", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2774_storage": { + "label": "struct Counters.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Role)3943_storage": { + "label": "struct FleekAccessControl.Role", + "members": [ + { + "label": "indexes", + "type": "t_mapping(t_address,t_uint256)", + "offset": 0, + "slot": "0" + }, + { + "label": "members", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "1b181d2bca62b1fd80201275e9cab2d4d42862c2ad867d1de97ac56fbf10d46f": { + "address": "0xb0b7Aa68d198B5C5B619276119F9aE5ED3803Fc1", + "txHash": "0xd963840b260f6fbca3b74b409f7260521fc3a3281269452d51987e35af7c2684", + "layout": { + "solcVersion": "0.8.7", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "101", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "102", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + }, + { + "label": "_collectionRolesVersion", + "offset": 0, + "slot": "151", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:26" + }, + { + "label": "_collectionRoles", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:28" + }, + { + "label": "_tokenRolesVersion", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_uint256,t_struct(Counter)2774_storage)", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:30" + }, + { + "label": "_tokenRoles", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:32" + }, + { + "label": "_tokenIds", + "offset": 0, + "slot": "155", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:44" + }, + { + "label": "_apps", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_struct(App)4606_storage)", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:45" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(Roles)3895": { + "label": "enum FleekAccessControl.Roles", + "members": ["Owner", "Controller"], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)": { + "label": "mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))": { + "label": "mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))": { + "label": "mapping(uint256 => mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(App)4606_storage)": { + "label": "mapping(uint256 => struct FleekERC721.App)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Build)4611_storage)": { + "label": "mapping(uint256 => struct FleekERC721.Build)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Counter)2774_storage)": { + "label": "mapping(uint256 => struct Counters.Counter)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(App)4606_storage": { + "label": "struct FleekERC721.App", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "externalURL", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "ENS", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "currentBuild", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "builds", + "type": "t_mapping(t_uint256,t_struct(Build)4611_storage)", + "offset": 0, + "slot": "5" + } + ], + "numberOfBytes": "192" + }, + "t_struct(Build)4611_storage": { + "label": "struct FleekERC721.Build", + "members": [ + { + "label": "commitHash", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "gitRepository", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2774_storage": { + "label": "struct Counters.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Role)3943_storage": { + "label": "struct FleekAccessControl.Role", + "members": [ + { + "label": "indexes", + "type": "t_mapping(t_address,t_uint256)", + "offset": 0, + "slot": "0" + }, + { + "label": "members", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "382a6d92125d95fa14a64a9072334fb34e8b9b32006a529ef84ce0ed9934204a": { + "address": "0x274b130B40b7F5ab45eBb14546b634d092F27c97", + "txHash": "0xffa19b5d5aa7fd65e1d16ec7190cd230642cded09188810fef5024ed4295d9eb", + "layout": { + "solcVersion": "0.8.7", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "101", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "102", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + }, + { + "label": "_collectionRolesVersion", + "offset": 0, + "slot": "151", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:26" + }, + { + "label": "_collectionRoles", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:28" + }, + { + "label": "_tokenRolesVersion", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_uint256,t_struct(Counter)2774_storage)", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:30" + }, + { + "label": "_tokenRoles", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:32" + }, + { + "label": "_tokenIds", + "offset": 0, + "slot": "155", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:44" + }, + { + "label": "_apps", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_struct(App)4606_storage)", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:45" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(Roles)3895": { + "label": "enum FleekAccessControl.Roles", + "members": ["Owner", "Controller"], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)": { + "label": "mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))": { + "label": "mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))": { + "label": "mapping(uint256 => mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(App)4606_storage)": { + "label": "mapping(uint256 => struct FleekERC721.App)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Build)4611_storage)": { + "label": "mapping(uint256 => struct FleekERC721.Build)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Counter)2774_storage)": { + "label": "mapping(uint256 => struct Counters.Counter)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(App)4606_storage": { + "label": "struct FleekERC721.App", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "externalURL", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "ENS", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "currentBuild", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "builds", + "type": "t_mapping(t_uint256,t_struct(Build)4611_storage)", + "offset": 0, + "slot": "5" + } + ], + "numberOfBytes": "192" + }, + "t_struct(Build)4611_storage": { + "label": "struct FleekERC721.Build", + "members": [ + { + "label": "commitHash", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "gitRepository", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2774_storage": { + "label": "struct Counters.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Role)3943_storage": { + "label": "struct FleekAccessControl.Role", + "members": [ + { + "label": "indexes", + "type": "t_mapping(t_address,t_uint256)", + "offset": 0, + "slot": "0" + }, + { + "label": "members", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "ce06a30659399e7b1f9bde4cc28eb5eb35862e14b743f8c0dfeee31a9e709e64": { + "address": "0x958D10c6DDfb78BeDCF9FC391a6334479ad15aA9", + "txHash": "0x85802bd619fe1124ca0ffbb97c76ad4bf7e741764331f8694d72a98752aa20bb", + "layout": { + "solcVersion": "0.8.7", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "101", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "102", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + }, + { + "label": "_collectionRolesVersion", + "offset": 0, + "slot": "151", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:26" + }, + { + "label": "_collectionRoles", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:28" + }, + { + "label": "_tokenRolesVersion", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_uint256,t_struct(Counter)2774_storage)", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:30" + }, + { + "label": "_tokenRoles", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:32" + }, + { + "label": "_tokenIds", + "offset": 0, + "slot": "155", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:44" + }, + { + "label": "_apps", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_struct(App)4606_storage)", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:45" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(Roles)3895": { + "label": "enum FleekAccessControl.Roles", + "members": ["Owner", "Controller"], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)": { + "label": "mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))": { + "label": "mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))": { + "label": "mapping(uint256 => mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(App)4606_storage)": { + "label": "mapping(uint256 => struct FleekERC721.App)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Build)4611_storage)": { + "label": "mapping(uint256 => struct FleekERC721.Build)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Counter)2774_storage)": { + "label": "mapping(uint256 => struct Counters.Counter)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(App)4606_storage": { + "label": "struct FleekERC721.App", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "externalURL", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "ENS", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "currentBuild", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "builds", + "type": "t_mapping(t_uint256,t_struct(Build)4611_storage)", + "offset": 0, + "slot": "5" + } + ], + "numberOfBytes": "192" + }, + "t_struct(Build)4611_storage": { + "label": "struct FleekERC721.Build", + "members": [ + { + "label": "commitHash", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "gitRepository", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2774_storage": { + "label": "struct Counters.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Role)3943_storage": { + "label": "struct FleekAccessControl.Role", + "members": [ + { + "label": "indexes", + "type": "t_mapping(t_address,t_uint256)", + "offset": 0, + "slot": "0" + }, + { + "label": "members", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "afdbe6b713cfe78d54145ec70934be60644c8d703b4e751e976f5a11268c6731": { + "address": "0x46Ef1B8Ab17fE66233cA344076C4104548BDd726", + "txHash": "0xb7784b772b1e93e264bac8794c4d2c52288594a61efe2cc7f87c0cb3426aa2dd", + "layout": { + "solcVersion": "0.8.7", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_name", + "offset": 0, + "slot": "101", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:25" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "102", + "type": "t_string_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:28" + }, + { + "label": "_owners", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:31" + }, + { + "label": "_balances", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:34" + }, + { + "label": "_tokenApprovals", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:37" + }, + { + "label": "_operatorApprovals", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:40" + }, + { + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage", + "contract": "ERC721Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol:514" + }, + { + "label": "_collectionRolesVersion", + "offset": 0, + "slot": "151", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:26" + }, + { + "label": "_collectionRoles", + "offset": 0, + "slot": "152", + "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:28" + }, + { + "label": "_tokenRolesVersion", + "offset": 0, + "slot": "153", + "type": "t_mapping(t_uint256,t_struct(Counter)2774_storage)", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:30" + }, + { + "label": "_tokenRoles", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))", + "contract": "FleekAccessControl", + "src": "contracts/FleekAccessControl.sol:32" + }, + { + "label": "_tokenIds", + "offset": 0, + "slot": "155", + "type": "t_struct(Counter)2774_storage", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:44" + }, + { + "label": "_apps", + "offset": 0, + "slot": "156", + "type": "t_mapping(t_uint256,t_struct(App)4606_storage)", + "contract": "FleekERC721", + "src": "contracts/FleekERC721.sol:45" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)44_storage": { + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_enum(Roles)3895": { + "label": "enum FleekAccessControl.Roles", + "members": ["Owner", "Controller"], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)": { + "label": "mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))": { + "label": "mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))": { + "label": "mapping(uint256 => mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)))", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(App)4606_storage)": { + "label": "mapping(uint256 => struct FleekERC721.App)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Build)4611_storage)": { + "label": "mapping(uint256 => struct FleekERC721.Build)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Counter)2774_storage)": { + "label": "mapping(uint256 => struct Counters.Counter)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(App)4606_storage": { + "label": "struct FleekERC721.App", + "members": [ + { + "label": "name", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "description", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + }, + { + "label": "externalURL", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + }, + { + "label": "ENS", + "type": "t_string_storage", + "offset": 0, + "slot": "3" + }, + { + "label": "currentBuild", + "type": "t_uint256", + "offset": 0, + "slot": "4" + }, + { + "label": "builds", + "type": "t_mapping(t_uint256,t_struct(Build)4611_storage)", + "offset": 0, + "slot": "5" + } + ], + "numberOfBytes": "192" + }, + "t_struct(Build)4611_storage": { + "label": "struct FleekERC721.Build", + "members": [ + { + "label": "commitHash", + "type": "t_string_storage", + "offset": 0, + "slot": "0" + }, + { + "label": "gitRepository", + "type": "t_string_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Counter)2774_storage": { + "label": "struct Counters.Counter", + "members": [ + { + "label": "_value", + "type": "t_uint256", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(Role)3943_storage": { + "label": "struct FleekAccessControl.Role", + "members": [ + { + "label": "indexes", + "type": "t_mapping(t_address,t_uint256)", + "offset": 0, + "slot": "0" + }, + { + "label": "members", + "type": "t_array(t_address)dyn_storage", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + } + } +} diff --git a/README.md b/README.md index 6976907..7a4c865 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ > 🚧 IMPORTANT 🚧 - This initiative is under development, so this repo should be treated as a WIP. The goals and the roadmap might change as the project is shaped. - ## ⚡ Overview This is the landing point for Fleek's initiative to implement infrastructure as Solidity contracts. @@ -154,7 +153,7 @@ $ yarn node:hardhat To deploy the contract on the HardHat network, execute: ``` -$ yarn deploy:local +$ yarn deploy:hardhat ``` If the execution is successful, you will see the contract address on your screen. diff --git a/contracts/FleekAccessControl.sol b/contracts/FleekAccessControl.sol index 7003e3e..19f250c 100644 --- a/contracts/FleekAccessControl.sol +++ b/contracts/FleekAccessControl.sol @@ -3,8 +3,9 @@ pragma solidity ^0.8.7; import "@openzeppelin/contracts/utils/Counters.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -contract FleekAccessControl { +contract FleekAccessControl is Initializable { using Counters for Counters.Counter; enum Roles { @@ -33,7 +34,7 @@ contract FleekAccessControl { /** * @dev Initializes the contract by granting the `Owner` role to the deployer. */ - constructor() { + function __FleekAccessControl_init() internal onlyInitializing { _grantCollectionRole(Roles.Owner, msg.sender); } diff --git a/contracts/FleekERC721.sol b/contracts/FleekERC721.sol index 71d9fa5..20f81a1 100644 --- a/contracts/FleekERC721.sol +++ b/contracts/FleekERC721.sol @@ -2,13 +2,15 @@ pragma solidity ^0.8.7; -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Base64.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; import "./FleekAccessControl.sol"; import "./util/FleekStrings.sol"; -contract FleekERC721 is ERC721, FleekAccessControl { +contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl { + using Strings for uint256; using Counters for Counters.Counter; using FleekStrings for FleekERC721.App; using FleekStrings for FleekERC721.AccessPoint; @@ -84,7 +86,10 @@ contract FleekERC721 is ERC721, FleekAccessControl { /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ - constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {} + function initialize(string memory _name, string memory _symbol) public initializer { + __ERC721_init(_name, _symbol); + __FleekAccessControl_init(); + } /** * @dev Checks if the AccessPoint exists. @@ -152,7 +157,7 @@ contract FleekERC721 is ERC721, FleekAccessControl { /** * @dev See {IERC165-supportsInterface}. */ - function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) { + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Upgradeable) returns (bool) { return super.supportsInterface(interfaceId); } diff --git a/deploy/local_deploy.js b/deploy/local_deploy.js deleted file mode 100644 index d2290cc..0000000 --- a/deploy/local_deploy.js +++ /dev/null @@ -1,29 +0,0 @@ -const contractName = 'FleekERC721'; - -const args = [ - 'FleekNFAs', // Collection name - 'FLKNFA', // Collection symbol -]; - -module.exports = async ({ getNamedAccounts, deployments }) => { - const { deploy, log } = deployments; - const namedAccounts = await getNamedAccounts(); - const { localDeployer: deployer } = namedAccounts; - - const deployResult = await deploy(contractName, { - from: deployer, - args, - }); - if (deployResult.newlyDeployed) { - log( - `Contract ${contractName} deployed at ${deployResult.address} using ${deployResult.receipt.gasUsed} gas by account ${deployer}` - ); - } else { - log( - `Using pre-existing contract ${contractName} at ${deployResult.address}` - ); - } -}; -//You can put an array of tags below. Tags can be anything and say when a this script should be run. So you can write different scripts for local, prod or other deploys -//For example when you run 'npx hardhat --network hardhat deploy --tags local' hardhat will run all deploy scripts that have the tag local, could be multiple dif scripts -module.exports.tags = ['local']; diff --git a/deploy/mumbai_deploy.js b/deploy/mumbai_deploy.js deleted file mode 100644 index 1ca10d0..0000000 --- a/deploy/mumbai_deploy.js +++ /dev/null @@ -1,35 +0,0 @@ -const contractName = 'FleekERC721'; - -const args = [ - 'FleekNFAs', // Collection name - 'FLKNFA', // Collection symbol -]; - -module.exports = async ({ getNamedAccounts, deployments }) => { - const { deploy, log } = deployments; - const namedAccounts = await getNamedAccounts(); - const { privateKey } = namedAccounts; - - if (!privateKey) { - log('Please set "PRIVATE_KEY" environment variable to deploy to Mumbai'); - throw new Error('Missing private key'); - } - - const deployResult = await deploy(contractName, { - from: privateKey, - args, - }); - - if (deployResult.newlyDeployed) { - log( - `Contract ${contractName} deployed at ${deployResult.address} using ${deployResult.receipt.gasUsed} gas` - ); - } else { - log( - `Using pre-existing contract ${contractName} at ${deployResult.address}` - ); - } -}; -//You can put an array of tags below. Tags can be anything and say when a this script should be run. So you can write different scripts for local, prod or other deploys -//For example when you run 'npx hardhat --network hardhat deploy --tags local' hardhat will run all deploy scripts that have the tag local, could be multiple dif scripts -module.exports.tags = ['mumbai']; diff --git a/deployments/mumbai/.chainId b/deployments/mumbai/.chainId deleted file mode 100644 index d7e2f72..0000000 --- a/deployments/mumbai/.chainId +++ /dev/null @@ -1 +0,0 @@ -80001 \ No newline at end of file diff --git a/deployments/mumbai/FleekERC721.json b/deployments/mumbai/FleekERC721.json index 83b19fa..fdb727c 100644 --- a/deployments/mumbai/FleekERC721.json +++ b/deployments/mumbai/FleekERC721.json @@ -1,22 +1,9 @@ { - "address": "0x34F21E970A7cd383eE429aDB5ed57bbc40ea2B57", + "timestamp": "1/17/2023, 12:39:20 PM", + "address": "0x21d7fBe220958A0F0f7cAE58780fe812EbcB3cd8", + "transactionHash": "0x715976ee8931f6e220c1e8d03c4aea779e3393def1342c2ff99867fe47125961", + "gasPrice": 1500000016, "abi": [ - { - "inputs": [ - { - "internalType": "string", - "name": "_name", - "type": "string" - }, - { - "internalType": "string", - "name": "_symbol", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, { "anonymous": false, "inputs": [ @@ -117,6 +104,19 @@ "name": "CollectionRoleRevoked", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -560,6 +560,24 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -601,11 +619,6 @@ "name": "description", "type": "string" }, - { - "internalType": "string", - "name": "image", - "type": "string" - }, { "internalType": "string", "name": "externalURL", @@ -857,24 +870,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "string", - "name": "_tokenImage", - "type": "string" - } - ], - "name": "setTokenImage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -968,256 +963,145 @@ "type": "function" } ], - "transactionHash": "0xb3e371a0ac604281b2284cae8b124c0627f7888d484b29364d362685ed8d3fa8", - "receipt": { - "to": null, - "from": "0xd4997d0FaCC83231b9F26a8B2155b4869E99946F", - "contractAddress": "0x34F21E970A7cd383eE429aDB5ed57bbc40ea2B57", - "transactionIndex": 2, - "gasUsed": "4978799", - "logsBloom": "0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000040000000000000000000000000808000000000000000000100000000004000000000020000000000000000000800000000000000000080000000000000000000000000000000000000000000000000000000080080000000000000000000200000000000000000000000000000000000000000000000000000000000004000000000010000000001000000000000000000000000000000100050000020008000000000000000000000000000000000000100000000000000000000100000", - "blockHash": "0x91388c9c42debf6289e680acbc1166508d630c605faaabdd0903fd97e945487e", - "transactionHash": "0xb3e371a0ac604281b2284cae8b124c0627f7888d484b29364d362685ed8d3fa8", - "logs": [ - { - "transactionIndex": 2, - "blockNumber": 30825341, - "transactionHash": "0xb3e371a0ac604281b2284cae8b124c0627f7888d484b29364d362685ed8d3fa8", - "address": "0x34F21E970A7cd383eE429aDB5ed57bbc40ea2B57", - "topics": [ - "0xcf081ed2b728e3115904be00eb8927b2375ff3401839b37f7accfa1bb2bee15c", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000d4997d0facc83231b9f26a8b2155b4869e99946f" - ], - "data": "0x000000000000000000000000d4997d0facc83231b9f26a8b2155b4869e99946f", - "logIndex": 4, - "blockHash": "0x91388c9c42debf6289e680acbc1166508d630c605faaabdd0903fd97e945487e" - }, - { - "transactionIndex": 2, - "blockNumber": 30825341, - "transactionHash": "0xb3e371a0ac604281b2284cae8b124c0627f7888d484b29364d362685ed8d3fa8", - "address": "0x0000000000000000000000000000000000001010", - "topics": [ - "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", - "0x0000000000000000000000000000000000000000000000000000000000001010", - "0x000000000000000000000000d4997d0facc83231b9f26a8b2155b4869e99946f", - "0x000000000000000000000000be188d6641e8b680743a4815dfa0f6208038960f" - ], - "data": "0x000000000000000000000000000000000000000000000000001a884976b46100000000000000000000000000000000000000000000000000109910547c6458b40000000000000000000000000000000000000000000028cda9b11829ab03e79c000000000000000000000000000000000000000000000000107e880b05aff7b40000000000000000000000000000000000000000000028cda9cba07321b8489c", - "logIndex": 5, - "blockHash": "0x91388c9c42debf6289e680acbc1166508d630c605faaabdd0903fd97e945487e" - } - ], - "blockNumber": 30825341, - "cumulativeGasUsed": "5044885", - "status": 1, - "byzantium": true - }, - "args": ["FleekNFAs", "FLKNFA"], - "numDeployments": 3, - "solcInputHash": "c05a9ff4c654910b408b84a2af4f1989", - "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"CollectionRoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"CollectionRoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"commitHash\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewBuild\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenDescription\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"ENS\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenENS\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"externalURL\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenExternalURL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"image\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenImage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenName\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"TokenRoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"TokenRoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"}],\"name\":\"getCollectionRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"}],\"name\":\"getTokenRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantCollectionRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantTokenRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasCollectionRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasTokenRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"image\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"externalURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"ENS\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"commitHash\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"gitRepository\",\"type\":\"string\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeCollectionRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeTokenRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_commitHash\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_gitRepository\",\"type\":\"string\"}],\"name\":\"setTokenBuild\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenDescription\",\"type\":\"string\"}],\"name\":\"setTokenDescription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenENS\",\"type\":\"string\"}],\"name\":\"setTokenENS\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenExternalURL\",\"type\":\"string\"}],\"name\":\"setTokenExternalURL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenImage\",\"type\":\"string\"}],\"name\":\"setTokenImage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenName\",\"type\":\"string\"}],\"name\":\"setTokenName\",\"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\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"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\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"See {IERC721-approve}.\"},\"balanceOf(address)\":{\"details\":\"See {IERC721-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Burns a previously minted `tokenId`. May emit a {Transfer} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenOwner` role.\"},\"constructor\":{\"details\":\"Initializes the contract by setting a `name` and a `symbol` to the token collection.\"},\"getApproved(uint256)\":{\"details\":\"See {IERC721-getApproved}.\"},\"getCollectionRoleMembers(uint8)\":{\"details\":\"Returns an array of addresses that all have the collection role.\"},\"getTokenRoleMembers(uint256,uint8)\":{\"details\":\"Returns an array of addresses that all have the same token role for a certain tokenId.\"},\"grantCollectionRole(uint8,address)\":{\"details\":\"Grants the collection role to an address. Requirements: - the caller should have the collection role.\"},\"grantTokenRole(uint256,uint8,address)\":{\"details\":\"Grants the token role to an address. Requirements: - the caller should have the token role.\"},\"hasCollectionRole(uint8,address)\":{\"details\":\"Returns `True` if a certain address has the collection role.\"},\"hasTokenRole(uint256,uint8,address)\":{\"details\":\"Returns `True` if a certain address has the token role.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC721-isApprovedForAll}.\"},\"mint(address,string,string,string,string,string,string,string)\":{\"details\":\"Mints a token and returns a tokenId. If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event. Requirements: - the caller must have ``collectionOwner``'s admin role.\"},\"name()\":{\"details\":\"See {IERC721Metadata-name}.\"},\"ownerOf(uint256)\":{\"details\":\"See {IERC721-ownerOf}.\"},\"revokeCollectionRole(uint8,address)\":{\"details\":\"Revokes the collection role of an address. Requirements: - the caller should have the collection role.\"},\"revokeTokenRole(uint256,uint8,address)\":{\"details\":\"Revokes the token role of an address. Requirements: - the caller should have the token role.\"},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC721-setApprovalForAll}.\"},\"setTokenBuild(uint256,string,string)\":{\"details\":\"Adds a new build to a minted `tokenId`'s builds mapping. May emit a {NewBuild} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenDescription(uint256,string)\":{\"details\":\"Updates the `description` metadata field of a minted `tokenId`. May emit a {NewTokenDescription} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenENS(uint256,string)\":{\"details\":\"Updates the `ENS` metadata field of a minted `tokenId`. May emit a {NewTokenENS} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenExternalURL(uint256,string)\":{\"details\":\"Updates the `externalURL` metadata field of a minted `tokenId`. May emit a {NewTokenExternalURL} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenImage(uint256,string)\":{\"details\":\"Updates the `image` metadata field of a minted `tokenId`. May emit a {NewTokenImage} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenName(uint256,string)\":{\"details\":\"Updates the `name` metadata field of a minted `tokenId`. May emit a {NewTokenName} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"symbol()\":{\"details\":\"See {IERC721Metadata-symbol}.\"},\"tokenURI(uint256)\":{\"details\":\"Returns the token metadata associated with the `tokenId`. Returns a based64 encoded string value of the URI. Requirements: - the tokenId must be minted and valid.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-transferFrom}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FleekERC721.sol\":\"FleekERC721\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC721.sol\\\";\\nimport \\\"./IERC721Receiver.sol\\\";\\nimport \\\"./extensions/IERC721Metadata.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\nimport \\\"../../utils/Strings.sol\\\";\\nimport \\\"../../utils/introspection/ERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\\n * {ERC721Enumerable}.\\n */\\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\\n using Address for address;\\n using Strings for uint256;\\n\\n // Token name\\n string private _name;\\n\\n // Token symbol\\n string private _symbol;\\n\\n // Mapping from token ID to owner address\\n mapping(uint256 => address) private _owners;\\n\\n // Mapping owner address to token count\\n mapping(address => uint256) private _balances;\\n\\n // Mapping from token ID to approved address\\n mapping(uint256 => address) private _tokenApprovals;\\n\\n // Mapping from owner to operator approvals\\n mapping(address => mapping(address => bool)) private _operatorApprovals;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\\n return\\n interfaceId == type(IERC721).interfaceId ||\\n interfaceId == type(IERC721Metadata).interfaceId ||\\n super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev See {IERC721-balanceOf}.\\n */\\n function balanceOf(address owner) public view virtual override returns (uint256) {\\n require(owner != address(0), \\\"ERC721: address zero is not a valid owner\\\");\\n return _balances[owner];\\n }\\n\\n /**\\n * @dev See {IERC721-ownerOf}.\\n */\\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\\n address owner = _ownerOf(tokenId);\\n require(owner != address(0), \\\"ERC721: invalid token ID\\\");\\n return owner;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-name}.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-symbol}.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev See {IERC721Metadata-tokenURI}.\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n\\n string memory baseURI = _baseURI();\\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \\\"\\\";\\n }\\n\\n /**\\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\\n * by default, can be overridden in child contracts.\\n */\\n function _baseURI() internal view virtual returns (string memory) {\\n return \\\"\\\";\\n }\\n\\n /**\\n * @dev See {IERC721-approve}.\\n */\\n function approve(address to, uint256 tokenId) public virtual override {\\n address owner = ERC721.ownerOf(tokenId);\\n require(to != owner, \\\"ERC721: approval to current owner\\\");\\n\\n require(\\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\\n \\\"ERC721: approve caller is not token owner or approved for all\\\"\\n );\\n\\n _approve(to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-getApproved}.\\n */\\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\\n _requireMinted(tokenId);\\n\\n return _tokenApprovals[tokenId];\\n }\\n\\n /**\\n * @dev See {IERC721-setApprovalForAll}.\\n */\\n function setApprovalForAll(address operator, bool approved) public virtual override {\\n _setApprovalForAll(_msgSender(), operator, approved);\\n }\\n\\n /**\\n * @dev See {IERC721-isApprovedForAll}.\\n */\\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\\n return _operatorApprovals[owner][operator];\\n }\\n\\n /**\\n * @dev See {IERC721-transferFrom}.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n //solhint-disable-next-line max-line-length\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n\\n _transfer(from, to, tokenId);\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) public virtual override {\\n safeTransferFrom(from, to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev See {IERC721-safeTransferFrom}.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) public virtual override {\\n require(_isApprovedOrOwner(_msgSender(), tokenId), \\\"ERC721: caller is not token owner or approved\\\");\\n _safeTransfer(from, to, tokenId, data);\\n }\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\\n *\\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\\n * implement alternative mechanisms to perform token transfer, such as signature-based.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeTransfer(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) internal virtual {\\n _transfer(from, to, tokenId);\\n require(_checkOnERC721Received(from, to, tokenId, data), \\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n }\\n\\n /**\\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\\n */\\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\\n return _owners[tokenId];\\n }\\n\\n /**\\n * @dev Returns whether `tokenId` exists.\\n *\\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\\n *\\n * Tokens start existing when they are minted (`_mint`),\\n * and stop existing when they are burned (`_burn`).\\n */\\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\\n return _ownerOf(tokenId) != address(0);\\n }\\n\\n /**\\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\\n address owner = ERC721.ownerOf(tokenId);\\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\\n }\\n\\n /**\\n * @dev Safely mints `tokenId` and transfers it to `to`.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _safeMint(address to, uint256 tokenId) internal virtual {\\n _safeMint(to, tokenId, \\\"\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\\n */\\n function _safeMint(\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) internal virtual {\\n _mint(to, tokenId);\\n require(\\n _checkOnERC721Received(address(0), to, tokenId, data),\\n \\\"ERC721: transfer to non ERC721Receiver implementer\\\"\\n );\\n }\\n\\n /**\\n * @dev Mints `tokenId` and transfers it to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\\n *\\n * Requirements:\\n *\\n * - `tokenId` must not exist.\\n * - `to` cannot be the zero address.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _mint(address to, uint256 tokenId) internal virtual {\\n require(to != address(0), \\\"ERC721: mint to the zero address\\\");\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n _beforeTokenTransfer(address(0), to, tokenId, 1);\\n\\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\\n require(!_exists(tokenId), \\\"ERC721: token already minted\\\");\\n\\n unchecked {\\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\\n // Given that tokens are minted one by one, it is impossible in practice that\\n // this ever happens. Might change if we allow batch minting.\\n // The ERC fails to describe this case.\\n _balances[to] += 1;\\n }\\n\\n _owners[tokenId] = to;\\n\\n emit Transfer(address(0), to, tokenId);\\n\\n _afterTokenTransfer(address(0), to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Destroys `tokenId`.\\n * The approval is cleared when the token is burned.\\n * This is an internal function that does not check if the sender is authorized to operate on the token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _burn(uint256 tokenId) internal virtual {\\n address owner = ERC721.ownerOf(tokenId);\\n\\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\\n\\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\\n owner = ERC721.ownerOf(tokenId);\\n\\n // Clear approvals\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // Cannot overflow, as that would require more tokens to be burned/transferred\\n // out than the owner initially received through minting and transferring in.\\n _balances[owner] -= 1;\\n }\\n delete _owners[tokenId];\\n\\n emit Transfer(owner, address(0), tokenId);\\n\\n _afterTokenTransfer(owner, address(0), tokenId, 1);\\n }\\n\\n /**\\n * @dev Transfers `tokenId` from `from` to `to`.\\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n *\\n * Emits a {Transfer} event.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 tokenId\\n ) internal virtual {\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n require(to != address(0), \\\"ERC721: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, tokenId, 1);\\n\\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\\n require(ERC721.ownerOf(tokenId) == from, \\\"ERC721: transfer from incorrect owner\\\");\\n\\n // Clear approvals from the previous owner\\n delete _tokenApprovals[tokenId];\\n\\n unchecked {\\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\\n // `from`'s balance is the number of token held, which is at least one before the current\\n // transfer.\\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\\n // all 2**256 token ids to be minted, which in practice is impossible.\\n _balances[from] -= 1;\\n _balances[to] += 1;\\n }\\n _owners[tokenId] = to;\\n\\n emit Transfer(from, to, tokenId);\\n\\n _afterTokenTransfer(from, to, tokenId, 1);\\n }\\n\\n /**\\n * @dev Approve `to` to operate on `tokenId`\\n *\\n * Emits an {Approval} event.\\n */\\n function _approve(address to, uint256 tokenId) internal virtual {\\n _tokenApprovals[tokenId] = to;\\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\\n }\\n\\n /**\\n * @dev Approve `operator` to operate on all of `owner` tokens\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function _setApprovalForAll(\\n address owner,\\n address operator,\\n bool approved\\n ) internal virtual {\\n require(owner != operator, \\\"ERC721: approve to caller\\\");\\n _operatorApprovals[owner][operator] = approved;\\n emit ApprovalForAll(owner, operator, approved);\\n }\\n\\n /**\\n * @dev Reverts if the `tokenId` has not been minted yet.\\n */\\n function _requireMinted(uint256 tokenId) internal view virtual {\\n require(_exists(tokenId), \\\"ERC721: invalid token ID\\\");\\n }\\n\\n /**\\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\\n * The call is not executed if the target address is not a contract.\\n *\\n * @param from address representing the previous owner of the given token ID\\n * @param to target address that will receive the tokens\\n * @param tokenId uint256 ID of the token to be transferred\\n * @param data bytes optional data to send along with the call\\n * @return bool whether the call correctly returned the expected magic value\\n */\\n function _checkOnERC721Received(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes memory data\\n ) private returns (bool) {\\n if (to.isContract()) {\\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\\n return retval == IERC721Receiver.onERC721Received.selector;\\n } catch (bytes memory reason) {\\n if (reason.length == 0) {\\n revert(\\\"ERC721: transfer to non ERC721Receiver implementer\\\");\\n } else {\\n /// @solidity memory-safe-assembly\\n assembly {\\n revert(add(32, reason), mload(reason))\\n }\\n }\\n }\\n } else {\\n return true;\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\\n * - When `from` is zero, the tokens will be minted for `to`.\\n * - When `to` is zero, ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256, /* firstTokenId */\\n uint256 batchSize\\n ) internal virtual {\\n if (batchSize > 1) {\\n if (from != address(0)) {\\n _balances[from] -= batchSize;\\n }\\n if (to != address(0)) {\\n _balances[to] += batchSize;\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\\n *\\n * Calling conditions:\\n *\\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\\n * - When `from` is zero, the tokens were minted for `to`.\\n * - When `to` is zero, ``from``'s tokens were burned.\\n * - `from` and `to` are never both zero.\\n * - `batchSize` is non-zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 firstTokenId,\\n uint256 batchSize\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0xd89f3585b211fc9e3408384a4c4efdc3a93b2f877a3821046fa01c219d35be1b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xab28a56179c1db258c9bf5235b382698cb650debecb51b23d12be9e241374b68\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC721.sol\\\";\\n\\n/**\\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\\n * @dev See https://eips.ethereum.org/EIPS/eip-721\\n */\\ninterface IERC721Metadata is IERC721 {\\n /**\\n * @dev Returns the token collection name.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the token collection symbol.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\\n */\\n function tokenURI(uint256 tokenId) external view returns (string memory);\\n}\\n\",\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Base64.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides a set of functions to operate with Base64 strings.\\n *\\n * _Available since v4.5._\\n */\\nlibrary Base64 {\\n /**\\n * @dev Base64 Encoding/Decoding Table\\n */\\n string internal constant _TABLE = \\\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\\\";\\n\\n /**\\n * @dev Converts a `bytes` to its Bytes64 `string` representation.\\n */\\n function encode(bytes memory data) internal pure returns (string memory) {\\n /**\\n * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\\n * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\\n */\\n if (data.length == 0) return \\\"\\\";\\n\\n // Loads the table into memory\\n string memory table = _TABLE;\\n\\n // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\\n // and split into 4 numbers of 6 bits.\\n // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\\n // - `data.length + 2` -> Round up\\n // - `/ 3` -> Number of 3-bytes chunks\\n // - `4 *` -> 4 characters for each chunk\\n string memory result = new string(4 * ((data.length + 2) / 3));\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Prepare the lookup table (skip the first \\\"length\\\" byte)\\n let tablePtr := add(table, 1)\\n\\n // Prepare result pointer, jump over length\\n let resultPtr := add(result, 32)\\n\\n // Run over the input, 3 bytes at a time\\n for {\\n let dataPtr := data\\n let endPtr := add(data, mload(data))\\n } lt(dataPtr, endPtr) {\\n\\n } {\\n // Advance 3 bytes\\n dataPtr := add(dataPtr, 3)\\n let input := mload(dataPtr)\\n\\n // To write each character, shift the 3 bytes (18 bits) chunk\\n // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\\n // and apply logical AND with 0x3F which is the number of\\n // the previous character in the ASCII table prior to the Base64 Table\\n // The result is then added to the table to get the character to write,\\n // and finally write it in the result pointer but with a left shift\\n // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\\n resultPtr := add(resultPtr, 1) // Advance\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\\n resultPtr := add(resultPtr, 1) // Advance\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\\n resultPtr := add(resultPtr, 1) // Advance\\n\\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\\n resultPtr := add(resultPtr, 1) // Advance\\n }\\n\\n // When data `bytes` is not exactly 3 bytes long\\n // it is padded with `=` characters at the end\\n switch mod(mload(data), 3)\\n case 1 {\\n mstore8(sub(resultPtr, 1), 0x3d)\\n mstore8(sub(resultPtr, 2), 0x3d)\\n }\\n case 2 {\\n mstore8(sub(resultPtr, 1), 0x3d)\\n }\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0x5f3461639fe20794cfb4db4a6d8477388a15b2e70a018043084b7c4bedfa8136\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Counters.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Counters\\n * @author Matt Condon (@shrugs)\\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\\n *\\n * Include with `using Counters for Counters.Counter;`\\n */\\nlibrary Counters {\\n struct Counter {\\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\\n // this feature: see https://github.com/ethereum/solidity/issues/4637\\n uint256 _value; // default: 0\\n }\\n\\n function current(Counter storage counter) internal view returns (uint256) {\\n return counter._value;\\n }\\n\\n function increment(Counter storage counter) internal {\\n unchecked {\\n counter._value += 1;\\n }\\n }\\n\\n function decrement(Counter storage counter) internal {\\n uint256 value = counter._value;\\n require(value > 0, \\\"Counter: decrement overflow\\\");\\n unchecked {\\n counter._value = value - 1;\\n }\\n }\\n\\n function reset(Counter storage counter) internal {\\n counter._value = 0;\\n }\\n}\\n\",\"keccak256\":\"0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"contracts/FleekAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/utils/Counters.sol\\\";\\n\\ncontract FleekAccessControl {\\n using Counters for Counters.Counter;\\n\\n enum Roles {\\n Owner,\\n Controller\\n }\\n\\n event TokenRoleGranted(uint256 indexed tokenId, Roles indexed role, address indexed toAddress, address byAddress);\\n event TokenRoleRevoked(uint256 indexed tokenId, Roles indexed role, address indexed toAddress, address byAddress);\\n event CollectionRoleGranted(Roles indexed role, address indexed toAddress, address byAddress);\\n event CollectionRoleRevoked(Roles indexed role, address indexed toAddress, address byAddress);\\n\\n struct Role {\\n mapping(address => uint256) indexes;\\n address[] members;\\n }\\n\\n Counters.Counter private _collectionRolesVersion;\\n // _collectionRoles[version][role]\\n mapping(uint256 => mapping(Roles => Role)) private _collectionRoles;\\n\\n mapping(uint256 => Counters.Counter) private _tokenRolesVersion;\\n // _tokenRoles[tokenId][version][role]\\n mapping(uint256 => mapping(uint256 => mapping(Roles => Role))) private _tokenRoles;\\n\\n /**\\n * @dev Initializes the contract by granting the `Owner` role to the deployer.\\n */\\n constructor() {\\n _grantCollectionRole(Roles.Owner, msg.sender);\\n }\\n\\n /**\\n * @dev Checks if the `msg.sender` has a certain role.\\n */\\n modifier requireCollectionRole(Roles role) {\\n require(\\n hasCollectionRole(role, msg.sender) || hasCollectionRole(Roles.Owner, msg.sender),\\n \\\"FleekAccessControl: must have collection role\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev Checks if the `msg.sender` has the `Token` role for a certain `tokenId`.\\n */\\n modifier requireTokenRole(uint256 tokenId, Roles role) {\\n require(\\n hasTokenRole(tokenId, role, msg.sender) || hasTokenRole(tokenId, Roles.Owner, msg.sender),\\n \\\"FleekAccessControl: must have token role\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev Grants the collection role to an address.\\n *\\n * Requirements:\\n *\\n * - the caller should have the collection role.\\n *\\n */\\n function grantCollectionRole(Roles role, address account) public requireCollectionRole(Roles.Owner) {\\n _grantCollectionRole(role, account);\\n }\\n\\n /**\\n * @dev Grants the token role to an address.\\n *\\n * Requirements:\\n *\\n * - the caller should have the token role.\\n *\\n */\\n function grantTokenRole(\\n uint256 tokenId,\\n Roles role,\\n address account\\n ) public requireTokenRole(tokenId, Roles.Owner) {\\n _grantTokenRole(tokenId, role, account);\\n }\\n\\n /**\\n * @dev Revokes the collection role of an address.\\n *\\n * Requirements:\\n *\\n * - the caller should have the collection role.\\n *\\n */\\n function revokeCollectionRole(Roles role, address account) public requireCollectionRole(Roles.Owner) {\\n _revokeCollectionRole(role, account);\\n }\\n\\n /**\\n * @dev Revokes the token role of an address.\\n *\\n * Requirements:\\n *\\n * - the caller should have the token role.\\n *\\n */\\n function revokeTokenRole(\\n uint256 tokenId,\\n Roles role,\\n address account\\n ) public requireTokenRole(tokenId, Roles.Owner) {\\n _revokeTokenRole(tokenId, role, account);\\n }\\n\\n /**\\n * @dev Returns `True` if a certain address has the collection role.\\n */\\n function hasCollectionRole(Roles role, address account) public view returns (bool) {\\n uint256 currentVersion = _collectionRolesVersion.current();\\n\\n return _collectionRoles[currentVersion][role].indexes[account] != 0;\\n }\\n\\n /**\\n * @dev Returns `True` if a certain address has the token role.\\n */\\n function hasTokenRole(uint256 tokenId, Roles role, address account) public view returns (bool) {\\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\\n return _tokenRoles[tokenId][currentVersion][role].indexes[account] != 0;\\n }\\n\\n /**\\n * @dev Returns an array of addresses that all have the collection role.\\n */\\n function getCollectionRoleMembers(Roles role) public view returns (address[] memory) {\\n uint256 currentVersion = _collectionRolesVersion.current();\\n return _collectionRoles[currentVersion][role].members;\\n }\\n\\n /**\\n * @dev Returns an array of addresses that all have the same token role for a certain tokenId.\\n */\\n function getTokenRoleMembers(uint256 tokenId, Roles role) public view returns (address[] memory) {\\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\\n return _tokenRoles[tokenId][currentVersion][role].members;\\n }\\n\\n /**\\n * @dev Grants the collection role to an address.\\n */\\n function _grantCollectionRole(Roles role, address account) internal {\\n uint256 currentVersion = _collectionRolesVersion.current();\\n _grantRole(_collectionRoles[currentVersion][role], account);\\n emit CollectionRoleGranted(role, account, msg.sender);\\n }\\n\\n /**\\n * @dev Revokes the collection role of an address.\\n */\\n function _revokeCollectionRole(Roles role, address account) internal {\\n uint256 currentVersion = _collectionRolesVersion.current();\\n _revokeRole(_collectionRoles[currentVersion][role], account);\\n emit CollectionRoleRevoked(role, account, msg.sender);\\n }\\n\\n /**\\n * @dev Grants the token role to an address.\\n */\\n function _grantTokenRole(uint256 tokenId, Roles role, address account) internal {\\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\\n _grantRole(_tokenRoles[tokenId][currentVersion][role], account);\\n emit TokenRoleGranted(tokenId, role, account, msg.sender);\\n }\\n\\n /**\\n * @dev Revokes the token role of an address.\\n */\\n function _revokeTokenRole(uint256 tokenId, Roles role, address account) internal {\\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\\n _revokeRole(_tokenRoles[tokenId][currentVersion][role], account);\\n emit TokenRoleRevoked(tokenId, role, account, msg.sender);\\n }\\n\\n /**\\n * @dev Grants a certain role to a certain address.\\n */\\n function _grantRole(Role storage role, address account) internal {\\n if (role.indexes[account] == 0) {\\n role.members.push(account);\\n role.indexes[account] = role.members.length;\\n }\\n }\\n\\n /**\\n * @dev Revokes a certain role from a certain address.\\n */\\n function _revokeRole(Role storage role, address account) internal {\\n if (role.indexes[account] != 0) {\\n uint256 index = role.indexes[account] - 1;\\n uint256 lastIndex = role.members.length - 1;\\n address lastAccount = role.members[lastIndex];\\n\\n role.members[index] = lastAccount;\\n role.indexes[lastAccount] = index + 1;\\n\\n role.members.pop();\\n delete role.indexes[account];\\n }\\n }\\n\\n /**\\n * @dev Clears all token roles for a certain tokenId.\\n * Should only be used for burning tokens.\\n */\\n function _clearAllTokenRoles(uint256 tokenId) internal {\\n _tokenRolesVersion[tokenId].increment();\\n }\\n\\n /**\\n * @dev Clears all token roles for a certain tokenId and grants the owner role to a new address.\\n * Should only be used for transferring tokens.\\n */\\n function _clearAllTokenRoles(uint256 tokenId, address newOwner) internal {\\n _clearAllTokenRoles(tokenId);\\n _grantTokenRole(tokenId, Roles.Owner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x116e95aebf5f69698c91d6b4605e934f19427ee43939eaf970df90d178d64cc0\",\"license\":\"MIT\"},\"contracts/FleekERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC721/ERC721.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Counters.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Base64.sol\\\";\\nimport \\\"./FleekAccessControl.sol\\\";\\n\\ncontract FleekERC721 is ERC721, FleekAccessControl {\\n using Strings for uint256;\\n using Counters for Counters.Counter;\\n\\n event NewBuild(uint256 indexed token, string indexed commitHash, address indexed triggeredBy);\\n event NewTokenName(uint256 indexed token, string indexed name, address indexed triggeredBy);\\n event NewTokenDescription(uint256 indexed token, string indexed description, address indexed triggeredBy);\\n event NewTokenImage(uint256 indexed token, string indexed image, address indexed triggeredBy);\\n event NewTokenExternalURL(uint256 indexed token, string indexed externalURL, address indexed triggeredBy);\\n event NewTokenENS(uint256 indexed token, string indexed ENS, address indexed triggeredBy);\\n\\n /**\\n * The properties are stored as string to keep consistency with\\n * other token contracts, we might consider changing for bytes32\\n * in the future due to gas optimization.\\n */\\n struct App {\\n string name; // Name of the site\\n string description; // Description about the site\\n string image; // Preview Image IPFS Link\\n string externalURL; // Site URL\\n string ENS; // ENS ID\\n uint256 currentBuild; // The current build number (Increments by one with each change, starts at zero)\\n mapping(uint256 => Build) builds; // Mapping to build details for each build number\\n }\\n\\n /**\\n * The metadata that is stored for each build.\\n */\\n struct Build {\\n string commitHash;\\n string gitRepository;\\n }\\n\\n Counters.Counter private _tokenIds;\\n mapping(uint256 => App) private _apps;\\n\\n /**\\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\\n */\\n constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}\\n\\n /**\\n * @dev Checks if msg.sender has the role of tokenOwner for a certain tokenId.\\n */\\n modifier requireTokenOwner(uint256 tokenId) {\\n require(msg.sender == ownerOf(tokenId), \\\"FleekERC721: must be token owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Mints a token and returns a tokenId.\\n *\\n * If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``collectionOwner``'s admin role.\\n *\\n */\\n function mint(\\n address to,\\n string memory name,\\n string memory description,\\n string memory image,\\n string memory externalURL,\\n string memory ENS,\\n string memory commitHash,\\n string memory gitRepository\\n ) public payable requireCollectionRole(Roles.Owner) returns (uint256) {\\n uint256 tokenId = _tokenIds.current();\\n _mint(to, tokenId);\\n _tokenIds.increment();\\n\\n App storage app = _apps[tokenId];\\n app.name = name;\\n app.description = description;\\n app.image = image;\\n app.externalURL = externalURL;\\n app.ENS = ENS;\\n\\n // The mint interaction is considered to be the first build of the site. Updates from now on all increment the currentBuild by one and update the mapping.\\n app.currentBuild = 0;\\n app.builds[0] = Build(commitHash, gitRepository);\\n\\n return tokenId;\\n }\\n\\n /**\\n * @dev Returns the token metadata associated with the `tokenId`.\\n *\\n * Returns a based64 encoded string value of the URI.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n *\\n */\\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\\n _requireMinted(tokenId);\\n address owner = ownerOf(tokenId);\\n App storage app = _apps[tokenId];\\n\\n // prettier-ignore\\n bytes memory dataURI = abi.encodePacked(\\n '{',\\n '\\\"name\\\":\\\"', app.name, '\\\",',\\n '\\\"description\\\":\\\"', app.description, '\\\",',\\n '\\\"owner\\\":\\\"', Strings.toHexString(uint160(owner), 20), '\\\",',\\n '\\\"external_url\\\":\\\"', app.externalURL, '\\\",',\\n '\\\"image\\\":\\\"', app.image, '\\\",',\\n '\\\"attributes\\\": [',\\n '{\\\"trait_type\\\": \\\"ENS\\\", \\\"value\\\":\\\"', app.ENS,'\\\"},',\\n '{\\\"trait_type\\\": \\\"Commit Hash\\\", \\\"value\\\":\\\"', app.builds[app.currentBuild].commitHash,'\\\"},',\\n '{\\\"trait_type\\\": \\\"Repository\\\", \\\"value\\\":\\\"', app.builds[app.currentBuild].gitRepository,'\\\"},',\\n '{\\\"trait_type\\\": \\\"Version\\\", \\\"value\\\":\\\"', Strings.toString(app.currentBuild),'\\\"}',\\n ']',\\n '}'\\n );\\n\\n return string(abi.encodePacked(_baseURI(), Base64.encode((dataURI))));\\n }\\n\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) {\\n return super.supportsInterface(interfaceId);\\n }\\n\\n /**\\n * @dev Override of _beforeTokenTransfer of ERC721.\\n * Here it needs to update the token controller roles for mint, burn and transfer.\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 tokenId,\\n uint256 batchSize\\n ) internal virtual override {\\n if (from != address(0) && to != address(0)) {\\n // Transfer\\n _clearAllTokenRoles(tokenId, to);\\n } else if (from == address(0)) {\\n // Mint\\n _grantTokenRole(tokenId, Roles.Owner, to);\\n } else if (to == address(0)) {\\n // Burn\\n _clearAllTokenRoles(tokenId);\\n }\\n super._beforeTokenTransfer(from, to, tokenId, batchSize);\\n }\\n\\n /**\\n * @dev A baseURI internal function implementation to be called in the `tokenURI` function.\\n */\\n function _baseURI() internal view virtual override returns (string memory) {\\n return \\\"data:application/json;base64,\\\";\\n }\\n\\n /**\\n * @dev Updates the `externalURL` metadata field of a minted `tokenId`.\\n *\\n * May emit a {NewTokenExternalURL} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenController` role.\\n *\\n */\\n function setTokenExternalURL(\\n uint256 tokenId,\\n string memory _tokenExternalURL\\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\\n _requireMinted(tokenId);\\n _apps[tokenId].externalURL = _tokenExternalURL;\\n emit NewTokenExternalURL(tokenId, _tokenExternalURL, msg.sender);\\n }\\n\\n /**\\n * @dev Updates the `ENS` metadata field of a minted `tokenId`.\\n *\\n * May emit a {NewTokenENS} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenController` role.\\n *\\n */\\n function setTokenENS(\\n uint256 tokenId,\\n string memory _tokenENS\\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\\n _requireMinted(tokenId);\\n _apps[tokenId].ENS = _tokenENS;\\n emit NewTokenENS(tokenId, _tokenENS, msg.sender);\\n }\\n\\n /**\\n * @dev Updates the `name` metadata field of a minted `tokenId`.\\n *\\n * May emit a {NewTokenName} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenController` role.\\n *\\n */\\n function setTokenName(\\n uint256 tokenId,\\n string memory _tokenName\\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\\n _requireMinted(tokenId);\\n _apps[tokenId].name = _tokenName;\\n emit NewTokenName(tokenId, _tokenName, msg.sender);\\n }\\n\\n /**\\n * @dev Updates the `description` metadata field of a minted `tokenId`.\\n *\\n * May emit a {NewTokenDescription} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenController` role.\\n *\\n */\\n function setTokenDescription(\\n uint256 tokenId,\\n string memory _tokenDescription\\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\\n _requireMinted(tokenId);\\n _apps[tokenId].description = _tokenDescription;\\n emit NewTokenDescription(tokenId, _tokenDescription, msg.sender);\\n }\\n\\n /**\\n * @dev Updates the `image` metadata field of a minted `tokenId`.\\n *\\n * May emit a {NewTokenImage} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenController` role.\\n *\\n */\\n function setTokenImage(\\n uint256 tokenId,\\n string memory _tokenImage\\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\\n _requireMinted(tokenId);\\n _apps[tokenId].image = _tokenImage;\\n emit NewTokenImage(tokenId, _tokenImage, msg.sender);\\n }\\n\\n /**\\n * @dev Adds a new build to a minted `tokenId`'s builds mapping.\\n *\\n * May emit a {NewBuild} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenController` role.\\n *\\n */\\n function setTokenBuild(\\n uint256 tokenId,\\n string memory _commitHash,\\n string memory _gitRepository\\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\\n _requireMinted(tokenId);\\n _apps[tokenId].builds[++_apps[tokenId].currentBuild] = Build(_commitHash, _gitRepository);\\n emit NewBuild(tokenId, _commitHash, msg.sender);\\n }\\n\\n /**\\n * @dev Burns a previously minted `tokenId`.\\n *\\n * May emit a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - the tokenId must be minted and valid.\\n * - the sender must have the `tokenOwner` role.\\n *\\n */\\n function burn(uint256 tokenId) public virtual requireTokenRole(tokenId, Roles.Owner) {\\n super._burn(tokenId);\\n\\n if (bytes(_apps[tokenId].externalURL).length != 0) {\\n delete _apps[tokenId];\\n }\\n }\\n}\\n\",\"keccak256\":\"0x39211104bcab98ab30986edfeee3fe179df4861c6f2b4d57980b56c8d546fd07\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162005d4738038062005d478339818101604052810190620000379190620003ab565b81818160009080519060200190620000519291906200027d565b5080600190805190602001906200006a9291906200027d565b505050620000806000336200008860201b60201c565b505062000645565b6000620000a160066200016d60201b62001b961760201c565b905062000102600760008381526020019081526020016000206000856001811115620000d257620000d162000593565b5b6001811115620000e757620000e662000593565b5b8152602001908152602001600020836200017b60201b60201c565b8173ffffffffffffffffffffffffffffffffffffffff168360018111156200012f576200012e62000593565b5b7fcf081ed2b728e3115904be00eb8927b2375ff3401839b37f7accfa1bb2bee15c3360405162000160919062000441565b60405180910390a3505050565b600081600001549050919050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415620002795781600101819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600101805490508260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b8280546200028b9062000527565b90600052602060002090601f016020900481019282620002af5760008555620002fb565b82601f10620002ca57805160ff1916838001178555620002fb565b82800160010185558215620002fb579182015b82811115620002fa578251825591602001919060010190620002dd565b5b5090506200030a91906200030e565b5090565b5b80821115620003295760008160009055506001016200030f565b5090565b6000620003446200033e8462000487565b6200045e565b90508281526020810184848401111562000363576200036262000625565b5b62000370848285620004f1565b509392505050565b600082601f83011262000390576200038f62000620565b5b8151620003a28482602086016200032d565b91505092915050565b60008060408385031215620003c557620003c46200062f565b5b600083015167ffffffffffffffff811115620003e657620003e56200062a565b5b620003f48582860162000378565b925050602083015167ffffffffffffffff8111156200041857620004176200062a565b5b620004268582860162000378565b9150509250929050565b6200043b81620004bd565b82525050565b600060208201905062000458600083018462000430565b92915050565b60006200046a6200047d565b90506200047882826200055d565b919050565b6000604051905090565b600067ffffffffffffffff821115620004a557620004a4620005f1565b5b620004b08262000634565b9050602081019050919050565b6000620004ca82620004d1565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b8381101562000511578082015181840152602081019050620004f4565b8381111562000521576000848401525b50505050565b600060028204905060018216806200054057607f821691505b60208210811415620005575762000556620005c2565b5b50919050565b620005688262000634565b810181811067ffffffffffffffff821117156200058a5762000589620005f1565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b6156f280620006556000396000f3fe6080604052600436106101c25760003560e01c806364140ec0116100f7578063b42dbe3811610095578063cdb0e89e11610064578063cdb0e89e14610673578063e94472501461069c578063e985e9c5146106d9578063f931517714610716576101c2565b8063b42dbe38146105a0578063b543be12146105dd578063b88d4fde1461060d578063c87b56dd14610636576101c2565b80638c3c0a44116100d15780638c3c0a44146104fa57806395d89b4114610523578063a22cb4651461054e578063a27d0b2714610577576101c2565b806364140ec01461046b57806370a082311461049457806378278cca146104d1576101c2565b80632d957aad116101645780633806f1521161013e5780633806f152146103b357806342842e0e146103dc57806342966c68146104055780636352211e1461042e576101c2565b80632d957aad146103105780632f1e8f0a14610339578063353b07a414610376576101c2565b8063081812fc116101a0578063081812fc14610258578063095ea7b31461029557806323b872dd146102be578063246a908b146102e7576101c2565b806301468deb146101c757806301ffc9a7146101f057806306fdde031461022d575b600080fd5b3480156101d357600080fd5b506101ee60048036038101906101e99190613ede565b61073f565b005b3480156101fc57600080fd5b5061021760048036038101906102129190613daa565b6107b1565b604051610224919061483b565b60405180910390f35b34801561023957600080fd5b506102426107c3565b60405161024f9190614856565b60405180910390f35b34801561026457600080fd5b5061027f600480360381019061027a9190613e71565b610855565b60405161028c91906147b2565b60405180910390f35b3480156102a157600080fd5b506102bc60048036038101906102b79190613d6a565b61089b565b005b3480156102ca57600080fd5b506102e560048036038101906102e09190613ada565b6109b3565b005b3480156102f357600080fd5b5061030e60048036038101906103099190613f31565b610a13565b005b34801561031c57600080fd5b5061033760048036038101906103329190613e31565b610b07565b005b34801561034557600080fd5b50610360600480360381019061035b9190613e9e565b610b73565b60405161036d9190614819565b60405180910390f35b34801561038257600080fd5b5061039d60048036038101906103989190613e04565b610c7e565b6040516103aa9190614819565b60405180910390f35b3480156103bf57600080fd5b506103da60048036038101906103d59190613f8d565b610d66565b005b3480156103e857600080fd5b5061040360048036038101906103fe9190613ada565b610ed1565b005b34801561041157600080fd5b5061042c60048036038101906104279190613e71565b610ef1565b005b34801561043a57600080fd5b5061045560048036038101906104509190613e71565b610ff8565b60405161046291906147b2565b60405180910390f35b34801561047757600080fd5b50610492600480360381019061048d9190613f31565b61107f565b005b3480156104a057600080fd5b506104bb60048036038101906104b69190613a6d565b611173565b6040516104c89190614a38565b60405180910390f35b3480156104dd57600080fd5b506104f860048036038101906104f39190613f31565b61122b565b005b34801561050657600080fd5b50610521600480360381019061051c9190613e31565b61131f565b005b34801561052f57600080fd5b5061053861138b565b6040516105459190614856565b60405180910390f35b34801561055a57600080fd5b5061057560048036038101906105709190613bb0565b61141d565b005b34801561058357600080fd5b5061059e60048036038101906105999190613ede565b611433565b005b3480156105ac57600080fd5b506105c760048036038101906105c29190613ede565b6114a5565b6040516105d4919061483b565b60405180910390f35b6105f760048036038101906105f29190613bf0565b61156d565b6040516106049190614a38565b60405180910390f35b34801561061957600080fd5b50610634600480360381019061062f9190613b2d565b611704565b005b34801561064257600080fd5b5061065d60048036038101906106589190613e71565b611766565b60405161066a9190614856565b60405180910390f35b34801561067f57600080fd5b5061069a60048036038101906106959190613f31565b611875565b005b3480156106a857600080fd5b506106c360048036038101906106be9190613e31565b611969565b6040516106d0919061483b565b60405180910390f35b3480156106e557600080fd5b5061070060048036038101906106fb9190613a9a565b611a0e565b60405161070d919061483b565b60405180910390f35b34801561072257600080fd5b5061073d60048036038101906107389190613f31565b611aa2565b005b82600061074d8282336114a5565b80610760575061075f826000336114a5565b5b61079f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079690614a18565b60405180910390fd5b6107aa858585611ba4565b5050505050565b60006107bc82611c8d565b9050919050565b6060600080546107d290614d60565b80601f01602080910402602001604051908101604052809291908181526020018280546107fe90614d60565b801561084b5780601f106108205761010080835404028352916020019161084b565b820191906000526020600020905b81548152906001019060200180831161082e57829003601f168201915b5050505050905090565b600061086082611d6f565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006108a682610ff8565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610917576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090e906149d8565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610936611dba565b73ffffffffffffffffffffffffffffffffffffffff16148061096557506109648161095f611dba565b611a0e565b5b6109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099b906149f8565b60405180910390fd5b6109ae8383611dc2565b505050565b6109c46109be611dba565b82611e7b565b610a03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fa90614898565b60405180910390fd5b610a0e838383611f10565b505050565b816001610a218282336114a5565b80610a345750610a33826000336114a5565b5b610a73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6a90614a18565b60405180910390fd5b610a7c84611d6f565b82600b60008681526020019081526020016000206001019080519060200190610aa692919061382c565b503373ffffffffffffffffffffffffffffffffffffffff1683604051610acc9190614606565b6040518091039020857fd771eaa1c1382b0a9867125fcd921fdeddd211538b5381353a877abfbe3b50a460405160405180910390a450505050565b6000610b138133611969565b80610b255750610b24600033611969565b5b610b64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5b90614918565b60405180910390fd5b610b6e838361220a565b505050565b60606000610b9260086000868152602001908152602001600020611b96565b90506009600085815260200190815260200160002060008281526020019081526020016000206000846001811115610bcd57610bcc614e6a565b5b6001811115610bdf57610bde614e6a565b5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015610c7057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c26575b505050505091505092915050565b60606000610c8c6006611b96565b9050600760008281526020019081526020016000206000846001811115610cb657610cb5614e6a565b5b6001811115610cc857610cc7614e6a565b5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015610d5957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610d0f575b5050505050915050919050565b826001610d748282336114a5565b80610d875750610d86826000336114a5565b5b610dc6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbd90614a18565b60405180910390fd5b610dcf85611d6f565b604051806040016040528085815260200184815250600b60008781526020019081526020016000206006016000600b600089815260200190815260200160002060050160008154610e1f90614dc3565b91905081905581526020019081526020016000206000820151816000019080519060200190610e4f92919061382c565b506020820151816001019080519060200190610e6c92919061382c565b509050503373ffffffffffffffffffffffffffffffffffffffff1684604051610e959190614606565b6040518091039020867f73b929bf4db6be678cdbc6d41a5fe0a2cbb84ca95572062c4a978d8bd80a41b160405160405180910390a45050505050565b610eec83838360405180602001604052806000815250611704565b505050565b806000610eff8282336114a5565b80610f125750610f11826000336114a5565b5b610f51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4890614a18565b60405180910390fd5b610f5a836122cf565b6000600b60008581526020019081526020016000206003018054610f7d90614d60565b905014610ff357600b600084815260200190815260200160002060008082016000610fa891906138b2565b600182016000610fb891906138b2565b600282016000610fc891906138b2565b600382016000610fd891906138b2565b600482016000610fe891906138b2565b600582016000905550505b505050565b6000806110048361241d565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106d906149b8565b60405180910390fd5b80915050919050565b81600161108d8282336114a5565b806110a0575061109f826000336114a5565b5b6110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d690614a18565b60405180910390fd5b6110e884611d6f565b82600b6000868152602001908152602001600020600201908051906020019061111292919061382c565b503373ffffffffffffffffffffffffffffffffffffffff16836040516111389190614606565b6040518091039020857f80f081796a13b5a4269815447e37462c5739a69ea7f1460301b595e0c4003d8360405160405180910390a450505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156111e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111db90614978565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b8160016112398282336114a5565b8061124c575061124b826000336114a5565b5b61128b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128290614a18565b60405180910390fd5b61129484611d6f565b82600b600086815260200190815260200160002060040190805190602001906112be92919061382c565b503373ffffffffffffffffffffffffffffffffffffffff16836040516112e49190614606565b6040518091039020857f91ce7fcd4462481791c3fe849f7049373c5b43ef44aed48e7f1ecce781586e1560405160405180910390a450505050565b600061132b8133611969565b8061133d575061133c600033611969565b5b61137c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137390614918565b60405180910390fd5b611386838361245a565b505050565b60606001805461139a90614d60565b80601f01602080910402602001604051908101604052809291908181526020018280546113c690614d60565b80156114135780601f106113e857610100808354040283529160200191611413565b820191906000526020600020905b8154815290600101906020018083116113f657829003601f168201915b5050505050905090565b61142f611428611dba565b838361251f565b5050565b8260006114418282336114a5565b806114545750611453826000336114a5565b5b611493576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148a90614a18565b60405180910390fd5b61149e85858561268c565b5050505050565b6000806114c360086000878152602001908152602001600020611b96565b905060006009600087815260200190815260200160002060008381526020019081526020016000206000866001811115611500576114ff614e6a565b5b600181111561151257611511614e6a565b5b815260200190815260200160002060000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414159150509392505050565b60008061157a8133611969565b8061158c575061158b600033611969565b5b6115cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c290614918565b60405180910390fd5b60006115d7600a611b96565b90506115e38b82612775565b6115ed600a612993565b6000600b600083815260200190815260200160002090508a81600001908051906020019061161c92919061382c565b508981600101908051906020019061163592919061382c565b508881600201908051906020019061164e92919061382c565b508781600301908051906020019061166792919061382c565b508681600401908051906020019061168092919061382c565b506000816005018190555060405180604001604052808781526020018681525081600601600080815260200190815260200160002060008201518160000190805190602001906116d192919061382c565b5060208201518160010190805190602001906116ee92919061382c565b5090505081935050505098975050505050505050565b61171561170f611dba565b83611e7b565b611754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161174b90614898565b60405180910390fd5b611760848484846129a9565b50505050565b606061177182611d6f565b600061177c83610ff8565b90506000600b60008581526020019081526020016000209050600081600001826001016117c08573ffffffffffffffffffffffffffffffffffffffff166014612a05565b846003018560020186600401876006016000896005015481526020019081526020016000206000018860060160008a6005015481526020019081526020016000206001016118118a60050154612c41565b60405160200161182999989796959493929190614641565b6040516020818303038152906040529050611842612d19565b61184b82612d56565b60405160200161185c92919061461d565b6040516020818303038152906040529350505050919050565b8160016118838282336114a5565b806118965750611895826000336114a5565b5b6118d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118cc90614a18565b60405180910390fd5b6118de84611d6f565b82600b6000868152602001908152602001600020600001908051906020019061190892919061382c565b503373ffffffffffffffffffffffffffffffffffffffff168360405161192e9190614606565b6040518091039020857ffbbfca16a2770c7ca6e7063ab1a7eea5fe441ffef818325db51752066a6b128a60405160405180910390a450505050565b6000806119766006611b96565b905060006007600083815260200190815260200160002060008660018111156119a2576119a1614e6a565b5b60018111156119b4576119b3614e6a565b5b815260200190815260200160002060000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141591505092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b816001611ab08282336114a5565b80611ac35750611ac2826000336114a5565b5b611b02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611af990614a18565b60405180910390fd5b611b0b84611d6f565b82600b60008681526020019081526020016000206003019080519060200190611b3592919061382c565b503373ffffffffffffffffffffffffffffffffffffffff1683604051611b5b9190614606565b6040518091039020857fedbf1209b3baa7c1b5c43052ce5c511e243b3241d9f67733141d14f1da88cba160405160405180910390a450505050565b600081600001549050919050565b6000611bc160086000868152602001908152602001600020611b96565b9050611c256009600086815260200190815260200160002060008381526020019081526020016000206000856001811115611bff57611bfe614e6a565b5b6001811115611c1157611c10614e6a565b5b815260200190815260200160002083612eba565b8173ffffffffffffffffffffffffffffffffffffffff16836001811115611c4f57611c4e614e6a565b5b857fe52d746e4c78c98c6bfa291b273406905c3e8550b7d911a6bea686368c2dc79d33604051611c7f91906147b2565b60405180910390a450505050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d5857507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611d685750611d67826130f9565b5b9050919050565b611d7881613163565b611db7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dae906149b8565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611e3583610ff8565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611e8783610ff8565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611ec95750611ec88185611a0e565b5b80611f0757508373ffffffffffffffffffffffffffffffffffffffff16611eef84610855565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611f3082610ff8565b73ffffffffffffffffffffffffffffffffffffffff1614611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d906148d8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ff6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fed90614938565b60405180910390fd5b61200383838360016131a4565b8273ffffffffffffffffffffffffffffffffffffffff1661202382610ff8565b73ffffffffffffffffffffffffffffffffffffffff1614612079576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612070906148d8565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461220583838360016132bb565b505050565b60006122166006611b96565b905061226960076000838152602001908152602001600020600085600181111561224357612242614e6a565b5b600181111561225557612254614e6a565b5b8152602001908152602001600020836132c1565b8173ffffffffffffffffffffffffffffffffffffffff1683600181111561229357612292614e6a565b5b7fcf081ed2b728e3115904be00eb8927b2375ff3401839b37f7accfa1bb2bee15c336040516122c291906147b2565b60405180910390a3505050565b60006122da82610ff8565b90506122ea8160008460016131a4565b6122f382610ff8565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46124198160008460016132bb565b5050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006124666006611b96565b90506124b960076000838152602001908152602001600020600085600181111561249357612492614e6a565b5b60018111156124a5576124a4614e6a565b5b815260200190815260200160002083612eba565b8173ffffffffffffffffffffffffffffffffffffffff168360018111156124e3576124e2614e6a565b5b7faeff57f0f5e4d3d10a37d4a70fde8ed67a95e67b251d5c512c0ea98c380d2f953360405161251291906147b2565b60405180910390a3505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561258e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161258590614958565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161267f919061483b565b60405180910390a3505050565b60006126a960086000868152602001908152602001600020611b96565b905061270d60096000868152602001908152602001600020600083815260200190815260200160002060008560018111156126e7576126e6614e6a565b5b60018111156126f9576126f8614e6a565b5b8152602001908152602001600020836132c1565b8173ffffffffffffffffffffffffffffffffffffffff1683600181111561273757612736614e6a565b5b857f0bf5a13b362503fcc74b8b9b1598aba2f3a9af85d05ba7978f7e9f447f22c2393360405161276791906147b2565b60405180910390a450505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156127e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127dc90614998565b60405180910390fd5b6127ee81613163565b1561282e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612825906148f8565b60405180910390fd5b61283c6000838360016131a4565b61284581613163565b15612885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161287c906148f8565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461298f6000838360016132bb565b5050565b6001816000016000828254019250508190555050565b6129b4848484611f10565b6129c0848484846133c2565b6129ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129f6906148b8565b60405180910390fd5b50505050565b606060006002836002612a189190614bf2565b612a229190614b6b565b67ffffffffffffffff811115612a3b57612a3a614f26565b5b6040519080825280601f01601f191660200182016040528015612a6d5781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612aa557612aa4614ef7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612b0957612b08614ef7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002612b499190614bf2565b612b539190614b6b565b90505b6001811115612bf3577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612b9557612b94614ef7565b5b1a60f81b828281518110612bac57612bab614ef7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080612bec90614d36565b9050612b56565b5060008414612c37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c2e90614878565b60405180910390fd5b8091505092915050565b606060006001612c5084613559565b01905060008167ffffffffffffffff811115612c6f57612c6e614f26565b5b6040519080825280601f01601f191660200182016040528015612ca15781602001600182028036833780820191505090505b509050600082602001820190505b600115612d0e578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612cf857612cf7614e3b565b5b0494506000851415612d0957612d0e565b612caf565b819350505050919050565b60606040518060400160405280601d81526020017f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815250905090565b6060600082511415612d7957604051806020016040528060008152509050612eb5565b600060405180606001604052806040815260200161567d6040913990506000600360028551612da89190614b6b565b612db29190614bc1565b6004612dbe9190614bf2565b67ffffffffffffffff811115612dd757612dd6614f26565b5b6040519080825280601f01601f191660200182016040528015612e095781602001600182028036833780820191505090505b509050600182016020820185865187015b80821015612e75576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845360018401935050612e1a565b5050600386510660018114612e915760028114612ea457612eac565b603d6001830353603d6002830353612eac565b603d60018303535b50505080925050505b919050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146130f557600060018360000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612f539190614c4c565b9050600060018460010180549050612f6b9190614c4c565b90506000846001018281548110612f8557612f84614ef7565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080856001018481548110612fc957612fc8614ef7565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018361301e9190614b6b565b8560000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508460010180548061307757613076614ec8565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558460000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555050505b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166131858361241d565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561320e5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b156132225761321d82846136ac565b6132a9565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613268576132638260008561268c565b6132a8565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156132a7576132a6826136c5565b5b5b5b6132b5848484846136e3565b50505050565b50505050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414156133be5781600101819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600101805490508260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b60006133e38473ffffffffffffffffffffffffffffffffffffffff16613809565b1561354c578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261340c611dba565b8786866040518563ffffffff1660e01b815260040161342e94939291906147cd565b602060405180830381600087803b15801561344857600080fd5b505af192505050801561347957506040513d601f19601f820116820180604052508101906134769190613dd7565b60015b6134fc573d80600081146134a9576040519150601f19603f3d011682016040523d82523d6000602084013e6134ae565b606091505b506000815114156134f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134eb906148b8565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613551565b600190505b949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106135b7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816135ad576135ac614e3b565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106135f4576d04ee2d6d415b85acef810000000083816135ea576135e9614e3b565b5b0492506020810190505b662386f26fc10000831061362357662386f26fc10000838161361957613618614e3b565b5b0492506010810190505b6305f5e100831061364c576305f5e100838161364257613641614e3b565b5b0492506008810190505b612710831061367157612710838161366757613666614e3b565b5b0492506004810190505b60648310613694576064838161368a57613689614e3b565b5b0492506002810190505b600a83106136a3576001810190505b80915050919050565b6136b5826136c5565b6136c18260008361268c565b5050565b6136e060086000838152602001908152602001600020612993565b50565b600181111561380357600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146137775780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461376f9190614c4c565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146138025780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546137fa9190614b6b565b925050819055505b5b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b82805461383890614d60565b90600052602060002090601f01602090048101928261385a57600085556138a1565b82601f1061387357805160ff19168380011785556138a1565b828001600101855582156138a1579182015b828111156138a0578251825591602001919060010190613885565b5b5090506138ae91906138f2565b5090565b5080546138be90614d60565b6000825580601f106138d057506138ef565b601f0160209004906000526020600020908101906138ee91906138f2565b5b50565b5b8082111561390b5760008160009055506001016138f3565b5090565b600061392261391d84614a78565b614a53565b90508281526020810184848401111561393e5761393d614f5a565b5b613949848285614cf4565b509392505050565b600061396461395f84614aa9565b614a53565b9050828152602081018484840111156139805761397f614f5a565b5b61398b848285614cf4565b509392505050565b6000813590506139a281615610565b92915050565b6000813590506139b781615627565b92915050565b6000813590506139cc8161563e565b92915050565b6000815190506139e18161563e565b92915050565b600082601f8301126139fc576139fb614f55565b5b8135613a0c84826020860161390f565b91505092915050565b600081359050613a2481615655565b92915050565b600082601f830112613a3f57613a3e614f55565b5b8135613a4f848260208601613951565b91505092915050565b600081359050613a6781615665565b92915050565b600060208284031215613a8357613a82614f64565b5b6000613a9184828501613993565b91505092915050565b60008060408385031215613ab157613ab0614f64565b5b6000613abf85828601613993565b9250506020613ad085828601613993565b9150509250929050565b600080600060608486031215613af357613af2614f64565b5b6000613b0186828701613993565b9350506020613b1286828701613993565b9250506040613b2386828701613a58565b9150509250925092565b60008060008060808587031215613b4757613b46614f64565b5b6000613b5587828801613993565b9450506020613b6687828801613993565b9350506040613b7787828801613a58565b925050606085013567ffffffffffffffff811115613b9857613b97614f5f565b5b613ba4878288016139e7565b91505092959194509250565b60008060408385031215613bc757613bc6614f64565b5b6000613bd585828601613993565b9250506020613be6858286016139a8565b9150509250929050565b600080600080600080600080610100898b031215613c1157613c10614f64565b5b6000613c1f8b828c01613993565b985050602089013567ffffffffffffffff811115613c4057613c3f614f5f565b5b613c4c8b828c01613a2a565b975050604089013567ffffffffffffffff811115613c6d57613c6c614f5f565b5b613c798b828c01613a2a565b965050606089013567ffffffffffffffff811115613c9a57613c99614f5f565b5b613ca68b828c01613a2a565b955050608089013567ffffffffffffffff811115613cc757613cc6614f5f565b5b613cd38b828c01613a2a565b94505060a089013567ffffffffffffffff811115613cf457613cf3614f5f565b5b613d008b828c01613a2a565b93505060c089013567ffffffffffffffff811115613d2157613d20614f5f565b5b613d2d8b828c01613a2a565b92505060e089013567ffffffffffffffff811115613d4e57613d4d614f5f565b5b613d5a8b828c01613a2a565b9150509295985092959890939650565b60008060408385031215613d8157613d80614f64565b5b6000613d8f85828601613993565b9250506020613da085828601613a58565b9150509250929050565b600060208284031215613dc057613dbf614f64565b5b6000613dce848285016139bd565b91505092915050565b600060208284031215613ded57613dec614f64565b5b6000613dfb848285016139d2565b91505092915050565b600060208284031215613e1a57613e19614f64565b5b6000613e2884828501613a15565b91505092915050565b60008060408385031215613e4857613e47614f64565b5b6000613e5685828601613a15565b9250506020613e6785828601613993565b9150509250929050565b600060208284031215613e8757613e86614f64565b5b6000613e9584828501613a58565b91505092915050565b60008060408385031215613eb557613eb4614f64565b5b6000613ec385828601613a58565b9250506020613ed485828601613a15565b9150509250929050565b600080600060608486031215613ef757613ef6614f64565b5b6000613f0586828701613a58565b9350506020613f1686828701613a15565b9250506040613f2786828701613993565b9150509250925092565b60008060408385031215613f4857613f47614f64565b5b6000613f5685828601613a58565b925050602083013567ffffffffffffffff811115613f7757613f76614f5f565b5b613f8385828601613a2a565b9150509250929050565b600080600060608486031215613fa657613fa5614f64565b5b6000613fb486828701613a58565b935050602084013567ffffffffffffffff811115613fd557613fd4614f5f565b5b613fe186828701613a2a565b925050604084013567ffffffffffffffff81111561400257614001614f5f565b5b61400e86828701613a2a565b9150509250925092565b60006140248383614030565b60208301905092915050565b61403981614c80565b82525050565b61404881614c80565b82525050565b600061405982614aff565b6140638185614b2d565b935061406e83614ada565b8060005b8381101561409f5781516140868882614018565b975061409183614b20565b925050600181019050614072565b5085935050505092915050565b6140b581614c92565b82525050565b60006140c682614b0a565b6140d08185614b3e565b93506140e0818560208601614d03565b6140e981614f69565b840191505092915050565b60006140ff82614b15565b6141098185614b4f565b9350614119818560208601614d03565b61412281614f69565b840191505092915050565b600061413882614b15565b6141428185614b60565b9350614152818560208601614d03565b80840191505092915050565b6000815461416b81614d60565b6141758186614b60565b9450600182166000811461419057600181146141a1576141d4565b60ff198316865281860193506141d4565b6141aa85614aea565b60005b838110156141cc578154818901526001820191506020810190506141ad565b838801955050505b50505092915050565b60006141ea602083614b4f565b91506141f582614f7a565b602082019050919050565b600061420d602d83614b4f565b915061421882614fa3565b604082019050919050565b6000614230601083614b60565b915061423b82614ff2565b601082019050919050565b6000614253603283614b4f565b915061425e8261501b565b604082019050919050565b6000614276600f83614b60565b91506142818261506a565b600f82019050919050565b6000614299600283614b60565b91506142a482615093565b600282019050919050565b60006142bc602583614b4f565b91506142c7826150bc565b604082019050919050565b60006142df602383614b60565b91506142ea8261510b565b602382019050919050565b6000614302601c83614b4f565b915061430d8261515a565b602082019050919050565b6000614325600383614b60565b915061433082615183565b600382019050919050565b6000614348602d83614b4f565b9150614353826151ac565b604082019050919050565b600061436b602483614b4f565b9150614376826151fb565b604082019050919050565b600061438e601983614b4f565b91506143998261524a565b602082019050919050565b60006143b1602683614b60565b91506143bc82615273565b602682019050919050565b60006143d4600883614b60565b91506143df826152c2565b600882019050919050565b60006143f7602983614b4f565b9150614402826152eb565b604082019050919050565b600061441a600983614b60565b91506144258261533a565b600982019050919050565b600061443d600283614b60565b915061444882615363565b600282019050919050565b6000614460602083614b4f565b915061446b8261538c565b602082019050919050565b6000614483600183614b60565b915061448e826153b5565b600182019050919050565b60006144a6600183614b60565b91506144b1826153de565b600182019050919050565b60006144c9600f83614b60565b91506144d482615407565b600f82019050919050565b60006144ec600983614b60565b91506144f782615430565b600982019050919050565b600061450f601883614b4f565b915061451a82615459565b602082019050919050565b6000614532601f83614b60565b915061453d82615482565b601f82019050919050565b6000614555600183614b60565b9150614560826154ab565b600182019050919050565b6000614578602183614b4f565b9150614583826154d4565b604082019050919050565b600061459b602783614b60565b91506145a682615523565b602782019050919050565b60006145be603d83614b4f565b91506145c982615572565b604082019050919050565b60006145e1602883614b4f565b91506145ec826155c1565b604082019050919050565b61460081614cea565b82525050565b6000614612828461412d565b915081905092915050565b6000614629828561412d565b9150614635828461412d565b91508190509392505050565b600061464c82614499565b9150614657826143c7565b9150614663828c61415e565b915061466e8261428c565b915061467982614269565b9150614685828b61415e565b91506146908261428c565b915061469b826144df565b91506146a7828a61412d565b91506146b28261428c565b91506146bd82614223565b91506146c9828961415e565b91506146d48261428c565b91506146df8261440d565b91506146eb828861415e565b91506146f68261428c565b9150614701826144bc565b915061470c82614525565b9150614718828761415e565b915061472382614318565b915061472e8261458e565b915061473a828661415e565b915061474582614318565b9150614750826143a4565b915061475c828561415e565b915061476782614318565b9150614772826142d2565b915061477e828461412d565b915061478982614430565b915061479482614548565b915061479f82614476565b91508190509a9950505050505050505050565b60006020820190506147c7600083018461403f565b92915050565b60006080820190506147e2600083018761403f565b6147ef602083018661403f565b6147fc60408301856145f7565b818103606083015261480e81846140bb565b905095945050505050565b60006020820190508181036000830152614833818461404e565b905092915050565b600060208201905061485060008301846140ac565b92915050565b6000602082019050818103600083015261487081846140f4565b905092915050565b60006020820190508181036000830152614891816141dd565b9050919050565b600060208201905081810360008301526148b181614200565b9050919050565b600060208201905081810360008301526148d181614246565b9050919050565b600060208201905081810360008301526148f1816142af565b9050919050565b60006020820190508181036000830152614911816142f5565b9050919050565b600060208201905081810360008301526149318161433b565b9050919050565b600060208201905081810360008301526149518161435e565b9050919050565b6000602082019050818103600083015261497181614381565b9050919050565b60006020820190508181036000830152614991816143ea565b9050919050565b600060208201905081810360008301526149b181614453565b9050919050565b600060208201905081810360008301526149d181614502565b9050919050565b600060208201905081810360008301526149f18161456b565b9050919050565b60006020820190508181036000830152614a11816145b1565b9050919050565b60006020820190508181036000830152614a31816145d4565b9050919050565b6000602082019050614a4d60008301846145f7565b92915050565b6000614a5d614a6e565b9050614a698282614d92565b919050565b6000604051905090565b600067ffffffffffffffff821115614a9357614a92614f26565b5b614a9c82614f69565b9050602081019050919050565b600067ffffffffffffffff821115614ac457614ac3614f26565b5b614acd82614f69565b9050602081019050919050565b6000819050602082019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b6000614b7682614cea565b9150614b8183614cea565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614bb657614bb5614e0c565b5b828201905092915050565b6000614bcc82614cea565b9150614bd783614cea565b925082614be757614be6614e3b565b5b828204905092915050565b6000614bfd82614cea565b9150614c0883614cea565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614c4157614c40614e0c565b5b828202905092915050565b6000614c5782614cea565b9150614c6283614cea565b925082821015614c7557614c74614e0c565b5b828203905092915050565b6000614c8b82614cca565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015614d21578082015181840152602081019050614d06565b83811115614d30576000848401525b50505050565b6000614d4182614cea565b91506000821415614d5557614d54614e0c565b5b600182039050919050565b60006002820490506001821680614d7857607f821691505b60208210811415614d8c57614d8b614e99565b5b50919050565b614d9b82614f69565b810181811067ffffffffffffffff82111715614dba57614db9614f26565b5b80604052505050565b6000614dce82614cea565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614e0157614e00614e0c565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b7f2265787465726e616c5f75726c223a2200000000000000000000000000000000600082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f226465736372697074696f6e223a220000000000000000000000000000000000600082015250565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b7f7b2274726169745f74797065223a202256657273696f6e222c202276616c756560008201527f223a220000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f227d2c0000000000000000000000000000000000000000000000000000000000600082015250565b7f466c65656b416363657373436f6e74726f6c3a206d757374206861766520636f60008201527f6c6c656374696f6e20726f6c6500000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f7b2274726169745f74797065223a20225265706f7369746f7279222c2022766160008201527f6c7565223a220000000000000000000000000000000000000000000000000000602082015250565b7f226e616d65223a22000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b7f22696d616765223a220000000000000000000000000000000000000000000000600082015250565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f7b00000000000000000000000000000000000000000000000000000000000000600082015250565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b7f226f776e6572223a220000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b7f7b2274726169745f74797065223a2022454e53222c202276616c7565223a2200600082015250565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f7b2274726169745f74797065223a2022436f6d6d69742048617368222c20227660008201527f616c7565223a2200000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b7f466c65656b416363657373436f6e74726f6c3a206d757374206861766520746f60008201527f6b656e20726f6c65000000000000000000000000000000000000000000000000602082015250565b61561981614c80565b811461562457600080fd5b50565b61563081614c92565b811461563b57600080fd5b50565b61564781614c9e565b811461565257600080fd5b50565b6002811061566257600080fd5b50565b61566e81614cea565b811461567957600080fd5b5056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122032e73f057e680b3e0d97f7ae6e09c69b55cd4f12df3c5c5724647ab397ebd9d264736f6c63430008070033", - "deployedBytecode": "0x6080604052600436106101c25760003560e01c806364140ec0116100f7578063b42dbe3811610095578063cdb0e89e11610064578063cdb0e89e14610673578063e94472501461069c578063e985e9c5146106d9578063f931517714610716576101c2565b8063b42dbe38146105a0578063b543be12146105dd578063b88d4fde1461060d578063c87b56dd14610636576101c2565b80638c3c0a44116100d15780638c3c0a44146104fa57806395d89b4114610523578063a22cb4651461054e578063a27d0b2714610577576101c2565b806364140ec01461046b57806370a082311461049457806378278cca146104d1576101c2565b80632d957aad116101645780633806f1521161013e5780633806f152146103b357806342842e0e146103dc57806342966c68146104055780636352211e1461042e576101c2565b80632d957aad146103105780632f1e8f0a14610339578063353b07a414610376576101c2565b8063081812fc116101a0578063081812fc14610258578063095ea7b31461029557806323b872dd146102be578063246a908b146102e7576101c2565b806301468deb146101c757806301ffc9a7146101f057806306fdde031461022d575b600080fd5b3480156101d357600080fd5b506101ee60048036038101906101e99190613ede565b61073f565b005b3480156101fc57600080fd5b5061021760048036038101906102129190613daa565b6107b1565b604051610224919061483b565b60405180910390f35b34801561023957600080fd5b506102426107c3565b60405161024f9190614856565b60405180910390f35b34801561026457600080fd5b5061027f600480360381019061027a9190613e71565b610855565b60405161028c91906147b2565b60405180910390f35b3480156102a157600080fd5b506102bc60048036038101906102b79190613d6a565b61089b565b005b3480156102ca57600080fd5b506102e560048036038101906102e09190613ada565b6109b3565b005b3480156102f357600080fd5b5061030e60048036038101906103099190613f31565b610a13565b005b34801561031c57600080fd5b5061033760048036038101906103329190613e31565b610b07565b005b34801561034557600080fd5b50610360600480360381019061035b9190613e9e565b610b73565b60405161036d9190614819565b60405180910390f35b34801561038257600080fd5b5061039d60048036038101906103989190613e04565b610c7e565b6040516103aa9190614819565b60405180910390f35b3480156103bf57600080fd5b506103da60048036038101906103d59190613f8d565b610d66565b005b3480156103e857600080fd5b5061040360048036038101906103fe9190613ada565b610ed1565b005b34801561041157600080fd5b5061042c60048036038101906104279190613e71565b610ef1565b005b34801561043a57600080fd5b5061045560048036038101906104509190613e71565b610ff8565b60405161046291906147b2565b60405180910390f35b34801561047757600080fd5b50610492600480360381019061048d9190613f31565b61107f565b005b3480156104a057600080fd5b506104bb60048036038101906104b69190613a6d565b611173565b6040516104c89190614a38565b60405180910390f35b3480156104dd57600080fd5b506104f860048036038101906104f39190613f31565b61122b565b005b34801561050657600080fd5b50610521600480360381019061051c9190613e31565b61131f565b005b34801561052f57600080fd5b5061053861138b565b6040516105459190614856565b60405180910390f35b34801561055a57600080fd5b5061057560048036038101906105709190613bb0565b61141d565b005b34801561058357600080fd5b5061059e60048036038101906105999190613ede565b611433565b005b3480156105ac57600080fd5b506105c760048036038101906105c29190613ede565b6114a5565b6040516105d4919061483b565b60405180910390f35b6105f760048036038101906105f29190613bf0565b61156d565b6040516106049190614a38565b60405180910390f35b34801561061957600080fd5b50610634600480360381019061062f9190613b2d565b611704565b005b34801561064257600080fd5b5061065d60048036038101906106589190613e71565b611766565b60405161066a9190614856565b60405180910390f35b34801561067f57600080fd5b5061069a60048036038101906106959190613f31565b611875565b005b3480156106a857600080fd5b506106c360048036038101906106be9190613e31565b611969565b6040516106d0919061483b565b60405180910390f35b3480156106e557600080fd5b5061070060048036038101906106fb9190613a9a565b611a0e565b60405161070d919061483b565b60405180910390f35b34801561072257600080fd5b5061073d60048036038101906107389190613f31565b611aa2565b005b82600061074d8282336114a5565b80610760575061075f826000336114a5565b5b61079f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079690614a18565b60405180910390fd5b6107aa858585611ba4565b5050505050565b60006107bc82611c8d565b9050919050565b6060600080546107d290614d60565b80601f01602080910402602001604051908101604052809291908181526020018280546107fe90614d60565b801561084b5780601f106108205761010080835404028352916020019161084b565b820191906000526020600020905b81548152906001019060200180831161082e57829003601f168201915b5050505050905090565b600061086082611d6f565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006108a682610ff8565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610917576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090e906149d8565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610936611dba565b73ffffffffffffffffffffffffffffffffffffffff16148061096557506109648161095f611dba565b611a0e565b5b6109a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099b906149f8565b60405180910390fd5b6109ae8383611dc2565b505050565b6109c46109be611dba565b82611e7b565b610a03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109fa90614898565b60405180910390fd5b610a0e838383611f10565b505050565b816001610a218282336114a5565b80610a345750610a33826000336114a5565b5b610a73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6a90614a18565b60405180910390fd5b610a7c84611d6f565b82600b60008681526020019081526020016000206001019080519060200190610aa692919061382c565b503373ffffffffffffffffffffffffffffffffffffffff1683604051610acc9190614606565b6040518091039020857fd771eaa1c1382b0a9867125fcd921fdeddd211538b5381353a877abfbe3b50a460405160405180910390a450505050565b6000610b138133611969565b80610b255750610b24600033611969565b5b610b64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b5b90614918565b60405180910390fd5b610b6e838361220a565b505050565b60606000610b9260086000868152602001908152602001600020611b96565b90506009600085815260200190815260200160002060008281526020019081526020016000206000846001811115610bcd57610bcc614e6a565b5b6001811115610bdf57610bde614e6a565b5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015610c7057602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610c26575b505050505091505092915050565b60606000610c8c6006611b96565b9050600760008281526020019081526020016000206000846001811115610cb657610cb5614e6a565b5b6001811115610cc857610cc7614e6a565b5b8152602001908152602001600020600101805480602002602001604051908101604052809291908181526020018280548015610d5957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610d0f575b5050505050915050919050565b826001610d748282336114a5565b80610d875750610d86826000336114a5565b5b610dc6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbd90614a18565b60405180910390fd5b610dcf85611d6f565b604051806040016040528085815260200184815250600b60008781526020019081526020016000206006016000600b600089815260200190815260200160002060050160008154610e1f90614dc3565b91905081905581526020019081526020016000206000820151816000019080519060200190610e4f92919061382c565b506020820151816001019080519060200190610e6c92919061382c565b509050503373ffffffffffffffffffffffffffffffffffffffff1684604051610e959190614606565b6040518091039020867f73b929bf4db6be678cdbc6d41a5fe0a2cbb84ca95572062c4a978d8bd80a41b160405160405180910390a45050505050565b610eec83838360405180602001604052806000815250611704565b505050565b806000610eff8282336114a5565b80610f125750610f11826000336114a5565b5b610f51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4890614a18565b60405180910390fd5b610f5a836122cf565b6000600b60008581526020019081526020016000206003018054610f7d90614d60565b905014610ff357600b600084815260200190815260200160002060008082016000610fa891906138b2565b600182016000610fb891906138b2565b600282016000610fc891906138b2565b600382016000610fd891906138b2565b600482016000610fe891906138b2565b600582016000905550505b505050565b6000806110048361241d565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106d906149b8565b60405180910390fd5b80915050919050565b81600161108d8282336114a5565b806110a0575061109f826000336114a5565b5b6110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d690614a18565b60405180910390fd5b6110e884611d6f565b82600b6000868152602001908152602001600020600201908051906020019061111292919061382c565b503373ffffffffffffffffffffffffffffffffffffffff16836040516111389190614606565b6040518091039020857f80f081796a13b5a4269815447e37462c5739a69ea7f1460301b595e0c4003d8360405160405180910390a450505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156111e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111db90614978565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b8160016112398282336114a5565b8061124c575061124b826000336114a5565b5b61128b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128290614a18565b60405180910390fd5b61129484611d6f565b82600b600086815260200190815260200160002060040190805190602001906112be92919061382c565b503373ffffffffffffffffffffffffffffffffffffffff16836040516112e49190614606565b6040518091039020857f91ce7fcd4462481791c3fe849f7049373c5b43ef44aed48e7f1ecce781586e1560405160405180910390a450505050565b600061132b8133611969565b8061133d575061133c600033611969565b5b61137c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161137390614918565b60405180910390fd5b611386838361245a565b505050565b60606001805461139a90614d60565b80601f01602080910402602001604051908101604052809291908181526020018280546113c690614d60565b80156114135780601f106113e857610100808354040283529160200191611413565b820191906000526020600020905b8154815290600101906020018083116113f657829003601f168201915b5050505050905090565b61142f611428611dba565b838361251f565b5050565b8260006114418282336114a5565b806114545750611453826000336114a5565b5b611493576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148a90614a18565b60405180910390fd5b61149e85858561268c565b5050505050565b6000806114c360086000878152602001908152602001600020611b96565b905060006009600087815260200190815260200160002060008381526020019081526020016000206000866001811115611500576114ff614e6a565b5b600181111561151257611511614e6a565b5b815260200190815260200160002060000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414159150509392505050565b60008061157a8133611969565b8061158c575061158b600033611969565b5b6115cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115c290614918565b60405180910390fd5b60006115d7600a611b96565b90506115e38b82612775565b6115ed600a612993565b6000600b600083815260200190815260200160002090508a81600001908051906020019061161c92919061382c565b508981600101908051906020019061163592919061382c565b508881600201908051906020019061164e92919061382c565b508781600301908051906020019061166792919061382c565b508681600401908051906020019061168092919061382c565b506000816005018190555060405180604001604052808781526020018681525081600601600080815260200190815260200160002060008201518160000190805190602001906116d192919061382c565b5060208201518160010190805190602001906116ee92919061382c565b5090505081935050505098975050505050505050565b61171561170f611dba565b83611e7b565b611754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161174b90614898565b60405180910390fd5b611760848484846129a9565b50505050565b606061177182611d6f565b600061177c83610ff8565b90506000600b60008581526020019081526020016000209050600081600001826001016117c08573ffffffffffffffffffffffffffffffffffffffff166014612a05565b846003018560020186600401876006016000896005015481526020019081526020016000206000018860060160008a6005015481526020019081526020016000206001016118118a60050154612c41565b60405160200161182999989796959493929190614641565b6040516020818303038152906040529050611842612d19565b61184b82612d56565b60405160200161185c92919061461d565b6040516020818303038152906040529350505050919050565b8160016118838282336114a5565b806118965750611895826000336114a5565b5b6118d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118cc90614a18565b60405180910390fd5b6118de84611d6f565b82600b6000868152602001908152602001600020600001908051906020019061190892919061382c565b503373ffffffffffffffffffffffffffffffffffffffff168360405161192e9190614606565b6040518091039020857ffbbfca16a2770c7ca6e7063ab1a7eea5fe441ffef818325db51752066a6b128a60405160405180910390a450505050565b6000806119766006611b96565b905060006007600083815260200190815260200160002060008660018111156119a2576119a1614e6a565b5b60018111156119b4576119b3614e6a565b5b815260200190815260200160002060000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141591505092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b816001611ab08282336114a5565b80611ac35750611ac2826000336114a5565b5b611b02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611af990614a18565b60405180910390fd5b611b0b84611d6f565b82600b60008681526020019081526020016000206003019080519060200190611b3592919061382c565b503373ffffffffffffffffffffffffffffffffffffffff1683604051611b5b9190614606565b6040518091039020857fedbf1209b3baa7c1b5c43052ce5c511e243b3241d9f67733141d14f1da88cba160405160405180910390a450505050565b600081600001549050919050565b6000611bc160086000868152602001908152602001600020611b96565b9050611c256009600086815260200190815260200160002060008381526020019081526020016000206000856001811115611bff57611bfe614e6a565b5b6001811115611c1157611c10614e6a565b5b815260200190815260200160002083612eba565b8173ffffffffffffffffffffffffffffffffffffffff16836001811115611c4f57611c4e614e6a565b5b857fe52d746e4c78c98c6bfa291b273406905c3e8550b7d911a6bea686368c2dc79d33604051611c7f91906147b2565b60405180910390a450505050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611d5857507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611d685750611d67826130f9565b5b9050919050565b611d7881613163565b611db7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dae906149b8565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611e3583610ff8565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611e8783610ff8565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611ec95750611ec88185611a0e565b5b80611f0757508373ffffffffffffffffffffffffffffffffffffffff16611eef84610855565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611f3082610ff8565b73ffffffffffffffffffffffffffffffffffffffff1614611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d906148d8565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ff6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fed90614938565b60405180910390fd5b61200383838360016131a4565b8273ffffffffffffffffffffffffffffffffffffffff1661202382610ff8565b73ffffffffffffffffffffffffffffffffffffffff1614612079576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612070906148d8565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461220583838360016132bb565b505050565b60006122166006611b96565b905061226960076000838152602001908152602001600020600085600181111561224357612242614e6a565b5b600181111561225557612254614e6a565b5b8152602001908152602001600020836132c1565b8173ffffffffffffffffffffffffffffffffffffffff1683600181111561229357612292614e6a565b5b7fcf081ed2b728e3115904be00eb8927b2375ff3401839b37f7accfa1bb2bee15c336040516122c291906147b2565b60405180910390a3505050565b60006122da82610ff8565b90506122ea8160008460016131a4565b6122f382610ff8565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46124198160008460016132bb565b5050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006124666006611b96565b90506124b960076000838152602001908152602001600020600085600181111561249357612492614e6a565b5b60018111156124a5576124a4614e6a565b5b815260200190815260200160002083612eba565b8173ffffffffffffffffffffffffffffffffffffffff168360018111156124e3576124e2614e6a565b5b7faeff57f0f5e4d3d10a37d4a70fde8ed67a95e67b251d5c512c0ea98c380d2f953360405161251291906147b2565b60405180910390a3505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561258e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161258590614958565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161267f919061483b565b60405180910390a3505050565b60006126a960086000868152602001908152602001600020611b96565b905061270d60096000868152602001908152602001600020600083815260200190815260200160002060008560018111156126e7576126e6614e6a565b5b60018111156126f9576126f8614e6a565b5b8152602001908152602001600020836132c1565b8173ffffffffffffffffffffffffffffffffffffffff1683600181111561273757612736614e6a565b5b857f0bf5a13b362503fcc74b8b9b1598aba2f3a9af85d05ba7978f7e9f447f22c2393360405161276791906147b2565b60405180910390a450505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156127e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127dc90614998565b60405180910390fd5b6127ee81613163565b1561282e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612825906148f8565b60405180910390fd5b61283c6000838360016131a4565b61284581613163565b15612885576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161287c906148f8565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461298f6000838360016132bb565b5050565b6001816000016000828254019250508190555050565b6129b4848484611f10565b6129c0848484846133c2565b6129ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129f6906148b8565b60405180910390fd5b50505050565b606060006002836002612a189190614bf2565b612a229190614b6b565b67ffffffffffffffff811115612a3b57612a3a614f26565b5b6040519080825280601f01601f191660200182016040528015612a6d5781602001600182028036833780820191505090505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612aa557612aa4614ef7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110612b0957612b08614ef7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006001846002612b499190614bf2565b612b539190614b6b565b90505b6001811115612bf3577f3031323334353637383961626364656600000000000000000000000000000000600f861660108110612b9557612b94614ef7565b5b1a60f81b828281518110612bac57612bab614ef7565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080612bec90614d36565b9050612b56565b5060008414612c37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c2e90614878565b60405180910390fd5b8091505092915050565b606060006001612c5084613559565b01905060008167ffffffffffffffff811115612c6f57612c6e614f26565b5b6040519080825280601f01601f191660200182016040528015612ca15781602001600182028036833780820191505090505b509050600082602001820190505b600115612d0e578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612cf857612cf7614e3b565b5b0494506000851415612d0957612d0e565b612caf565b819350505050919050565b60606040518060400160405280601d81526020017f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815250905090565b6060600082511415612d7957604051806020016040528060008152509050612eb5565b600060405180606001604052806040815260200161567d6040913990506000600360028551612da89190614b6b565b612db29190614bc1565b6004612dbe9190614bf2565b67ffffffffffffffff811115612dd757612dd6614f26565b5b6040519080825280601f01601f191660200182016040528015612e095781602001600182028036833780820191505090505b509050600182016020820185865187015b80821015612e75576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845360018401935050612e1a565b5050600386510660018114612e915760028114612ea457612eac565b603d6001830353603d6002830353612eac565b603d60018303535b50505080925050505b919050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146130f557600060018360000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612f539190614c4c565b9050600060018460010180549050612f6b9190614c4c565b90506000846001018281548110612f8557612f84614ef7565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080856001018481548110612fc957612fc8614ef7565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018361301e9190614b6b565b8560000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508460010180548061307757613076614ec8565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558460000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090555050505b5050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166131858361241d565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561320e5750600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b156132225761321d82846136ac565b6132a9565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415613268576132638260008561268c565b6132a8565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156132a7576132a6826136c5565b5b5b5b6132b5848484846136e3565b50505050565b50505050565b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414156133be5781600101819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600101805490508260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b5050565b60006133e38473ffffffffffffffffffffffffffffffffffffffff16613809565b1561354c578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261340c611dba565b8786866040518563ffffffff1660e01b815260040161342e94939291906147cd565b602060405180830381600087803b15801561344857600080fd5b505af192505050801561347957506040513d601f19601f820116820180604052508101906134769190613dd7565b60015b6134fc573d80600081146134a9576040519150601f19603f3d011682016040523d82523d6000602084013e6134ae565b606091505b506000815114156134f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134eb906148b8565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613551565b600190505b949350505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106135b7577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816135ad576135ac614e3b565b5b0492506040810190505b6d04ee2d6d415b85acef810000000083106135f4576d04ee2d6d415b85acef810000000083816135ea576135e9614e3b565b5b0492506020810190505b662386f26fc10000831061362357662386f26fc10000838161361957613618614e3b565b5b0492506010810190505b6305f5e100831061364c576305f5e100838161364257613641614e3b565b5b0492506008810190505b612710831061367157612710838161366757613666614e3b565b5b0492506004810190505b60648310613694576064838161368a57613689614e3b565b5b0492506002810190505b600a83106136a3576001810190505b80915050919050565b6136b5826136c5565b6136c18260008361268c565b5050565b6136e060086000838152602001908152602001600020612993565b50565b600181111561380357600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16146137775780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461376f9190614c4c565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146138025780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546137fa9190614b6b565b925050819055505b5b50505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b82805461383890614d60565b90600052602060002090601f01602090048101928261385a57600085556138a1565b82601f1061387357805160ff19168380011785556138a1565b828001600101855582156138a1579182015b828111156138a0578251825591602001919060010190613885565b5b5090506138ae91906138f2565b5090565b5080546138be90614d60565b6000825580601f106138d057506138ef565b601f0160209004906000526020600020908101906138ee91906138f2565b5b50565b5b8082111561390b5760008160009055506001016138f3565b5090565b600061392261391d84614a78565b614a53565b90508281526020810184848401111561393e5761393d614f5a565b5b613949848285614cf4565b509392505050565b600061396461395f84614aa9565b614a53565b9050828152602081018484840111156139805761397f614f5a565b5b61398b848285614cf4565b509392505050565b6000813590506139a281615610565b92915050565b6000813590506139b781615627565b92915050565b6000813590506139cc8161563e565b92915050565b6000815190506139e18161563e565b92915050565b600082601f8301126139fc576139fb614f55565b5b8135613a0c84826020860161390f565b91505092915050565b600081359050613a2481615655565b92915050565b600082601f830112613a3f57613a3e614f55565b5b8135613a4f848260208601613951565b91505092915050565b600081359050613a6781615665565b92915050565b600060208284031215613a8357613a82614f64565b5b6000613a9184828501613993565b91505092915050565b60008060408385031215613ab157613ab0614f64565b5b6000613abf85828601613993565b9250506020613ad085828601613993565b9150509250929050565b600080600060608486031215613af357613af2614f64565b5b6000613b0186828701613993565b9350506020613b1286828701613993565b9250506040613b2386828701613a58565b9150509250925092565b60008060008060808587031215613b4757613b46614f64565b5b6000613b5587828801613993565b9450506020613b6687828801613993565b9350506040613b7787828801613a58565b925050606085013567ffffffffffffffff811115613b9857613b97614f5f565b5b613ba4878288016139e7565b91505092959194509250565b60008060408385031215613bc757613bc6614f64565b5b6000613bd585828601613993565b9250506020613be6858286016139a8565b9150509250929050565b600080600080600080600080610100898b031215613c1157613c10614f64565b5b6000613c1f8b828c01613993565b985050602089013567ffffffffffffffff811115613c4057613c3f614f5f565b5b613c4c8b828c01613a2a565b975050604089013567ffffffffffffffff811115613c6d57613c6c614f5f565b5b613c798b828c01613a2a565b965050606089013567ffffffffffffffff811115613c9a57613c99614f5f565b5b613ca68b828c01613a2a565b955050608089013567ffffffffffffffff811115613cc757613cc6614f5f565b5b613cd38b828c01613a2a565b94505060a089013567ffffffffffffffff811115613cf457613cf3614f5f565b5b613d008b828c01613a2a565b93505060c089013567ffffffffffffffff811115613d2157613d20614f5f565b5b613d2d8b828c01613a2a565b92505060e089013567ffffffffffffffff811115613d4e57613d4d614f5f565b5b613d5a8b828c01613a2a565b9150509295985092959890939650565b60008060408385031215613d8157613d80614f64565b5b6000613d8f85828601613993565b9250506020613da085828601613a58565b9150509250929050565b600060208284031215613dc057613dbf614f64565b5b6000613dce848285016139bd565b91505092915050565b600060208284031215613ded57613dec614f64565b5b6000613dfb848285016139d2565b91505092915050565b600060208284031215613e1a57613e19614f64565b5b6000613e2884828501613a15565b91505092915050565b60008060408385031215613e4857613e47614f64565b5b6000613e5685828601613a15565b9250506020613e6785828601613993565b9150509250929050565b600060208284031215613e8757613e86614f64565b5b6000613e9584828501613a58565b91505092915050565b60008060408385031215613eb557613eb4614f64565b5b6000613ec385828601613a58565b9250506020613ed485828601613a15565b9150509250929050565b600080600060608486031215613ef757613ef6614f64565b5b6000613f0586828701613a58565b9350506020613f1686828701613a15565b9250506040613f2786828701613993565b9150509250925092565b60008060408385031215613f4857613f47614f64565b5b6000613f5685828601613a58565b925050602083013567ffffffffffffffff811115613f7757613f76614f5f565b5b613f8385828601613a2a565b9150509250929050565b600080600060608486031215613fa657613fa5614f64565b5b6000613fb486828701613a58565b935050602084013567ffffffffffffffff811115613fd557613fd4614f5f565b5b613fe186828701613a2a565b925050604084013567ffffffffffffffff81111561400257614001614f5f565b5b61400e86828701613a2a565b9150509250925092565b60006140248383614030565b60208301905092915050565b61403981614c80565b82525050565b61404881614c80565b82525050565b600061405982614aff565b6140638185614b2d565b935061406e83614ada565b8060005b8381101561409f5781516140868882614018565b975061409183614b20565b925050600181019050614072565b5085935050505092915050565b6140b581614c92565b82525050565b60006140c682614b0a565b6140d08185614b3e565b93506140e0818560208601614d03565b6140e981614f69565b840191505092915050565b60006140ff82614b15565b6141098185614b4f565b9350614119818560208601614d03565b61412281614f69565b840191505092915050565b600061413882614b15565b6141428185614b60565b9350614152818560208601614d03565b80840191505092915050565b6000815461416b81614d60565b6141758186614b60565b9450600182166000811461419057600181146141a1576141d4565b60ff198316865281860193506141d4565b6141aa85614aea565b60005b838110156141cc578154818901526001820191506020810190506141ad565b838801955050505b50505092915050565b60006141ea602083614b4f565b91506141f582614f7a565b602082019050919050565b600061420d602d83614b4f565b915061421882614fa3565b604082019050919050565b6000614230601083614b60565b915061423b82614ff2565b601082019050919050565b6000614253603283614b4f565b915061425e8261501b565b604082019050919050565b6000614276600f83614b60565b91506142818261506a565b600f82019050919050565b6000614299600283614b60565b91506142a482615093565b600282019050919050565b60006142bc602583614b4f565b91506142c7826150bc565b604082019050919050565b60006142df602383614b60565b91506142ea8261510b565b602382019050919050565b6000614302601c83614b4f565b915061430d8261515a565b602082019050919050565b6000614325600383614b60565b915061433082615183565b600382019050919050565b6000614348602d83614b4f565b9150614353826151ac565b604082019050919050565b600061436b602483614b4f565b9150614376826151fb565b604082019050919050565b600061438e601983614b4f565b91506143998261524a565b602082019050919050565b60006143b1602683614b60565b91506143bc82615273565b602682019050919050565b60006143d4600883614b60565b91506143df826152c2565b600882019050919050565b60006143f7602983614b4f565b9150614402826152eb565b604082019050919050565b600061441a600983614b60565b91506144258261533a565b600982019050919050565b600061443d600283614b60565b915061444882615363565b600282019050919050565b6000614460602083614b4f565b915061446b8261538c565b602082019050919050565b6000614483600183614b60565b915061448e826153b5565b600182019050919050565b60006144a6600183614b60565b91506144b1826153de565b600182019050919050565b60006144c9600f83614b60565b91506144d482615407565b600f82019050919050565b60006144ec600983614b60565b91506144f782615430565b600982019050919050565b600061450f601883614b4f565b915061451a82615459565b602082019050919050565b6000614532601f83614b60565b915061453d82615482565b601f82019050919050565b6000614555600183614b60565b9150614560826154ab565b600182019050919050565b6000614578602183614b4f565b9150614583826154d4565b604082019050919050565b600061459b602783614b60565b91506145a682615523565b602782019050919050565b60006145be603d83614b4f565b91506145c982615572565b604082019050919050565b60006145e1602883614b4f565b91506145ec826155c1565b604082019050919050565b61460081614cea565b82525050565b6000614612828461412d565b915081905092915050565b6000614629828561412d565b9150614635828461412d565b91508190509392505050565b600061464c82614499565b9150614657826143c7565b9150614663828c61415e565b915061466e8261428c565b915061467982614269565b9150614685828b61415e565b91506146908261428c565b915061469b826144df565b91506146a7828a61412d565b91506146b28261428c565b91506146bd82614223565b91506146c9828961415e565b91506146d48261428c565b91506146df8261440d565b91506146eb828861415e565b91506146f68261428c565b9150614701826144bc565b915061470c82614525565b9150614718828761415e565b915061472382614318565b915061472e8261458e565b915061473a828661415e565b915061474582614318565b9150614750826143a4565b915061475c828561415e565b915061476782614318565b9150614772826142d2565b915061477e828461412d565b915061478982614430565b915061479482614548565b915061479f82614476565b91508190509a9950505050505050505050565b60006020820190506147c7600083018461403f565b92915050565b60006080820190506147e2600083018761403f565b6147ef602083018661403f565b6147fc60408301856145f7565b818103606083015261480e81846140bb565b905095945050505050565b60006020820190508181036000830152614833818461404e565b905092915050565b600060208201905061485060008301846140ac565b92915050565b6000602082019050818103600083015261487081846140f4565b905092915050565b60006020820190508181036000830152614891816141dd565b9050919050565b600060208201905081810360008301526148b181614200565b9050919050565b600060208201905081810360008301526148d181614246565b9050919050565b600060208201905081810360008301526148f1816142af565b9050919050565b60006020820190508181036000830152614911816142f5565b9050919050565b600060208201905081810360008301526149318161433b565b9050919050565b600060208201905081810360008301526149518161435e565b9050919050565b6000602082019050818103600083015261497181614381565b9050919050565b60006020820190508181036000830152614991816143ea565b9050919050565b600060208201905081810360008301526149b181614453565b9050919050565b600060208201905081810360008301526149d181614502565b9050919050565b600060208201905081810360008301526149f18161456b565b9050919050565b60006020820190508181036000830152614a11816145b1565b9050919050565b60006020820190508181036000830152614a31816145d4565b9050919050565b6000602082019050614a4d60008301846145f7565b92915050565b6000614a5d614a6e565b9050614a698282614d92565b919050565b6000604051905090565b600067ffffffffffffffff821115614a9357614a92614f26565b5b614a9c82614f69565b9050602081019050919050565b600067ffffffffffffffff821115614ac457614ac3614f26565b5b614acd82614f69565b9050602081019050919050565b6000819050602082019050919050565b60008190508160005260206000209050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b6000614b7682614cea565b9150614b8183614cea565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614bb657614bb5614e0c565b5b828201905092915050565b6000614bcc82614cea565b9150614bd783614cea565b925082614be757614be6614e3b565b5b828204905092915050565b6000614bfd82614cea565b9150614c0883614cea565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614c4157614c40614e0c565b5b828202905092915050565b6000614c5782614cea565b9150614c6283614cea565b925082821015614c7557614c74614e0c565b5b828203905092915050565b6000614c8b82614cca565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b83811015614d21578082015181840152602081019050614d06565b83811115614d30576000848401525b50505050565b6000614d4182614cea565b91506000821415614d5557614d54614e0c565b5b600182039050919050565b60006002820490506001821680614d7857607f821691505b60208210811415614d8c57614d8b614e99565b5b50919050565b614d9b82614f69565b810181811067ffffffffffffffff82111715614dba57614db9614f26565b5b80604052505050565b6000614dce82614cea565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614e0157614e00614e0c565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b7f2265787465726e616c5f75726c223a2200000000000000000000000000000000600082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f226465736372697074696f6e223a220000000000000000000000000000000000600082015250565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b7f7b2274726169745f74797065223a202256657273696f6e222c202276616c756560008201527f223a220000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f227d2c0000000000000000000000000000000000000000000000000000000000600082015250565b7f466c65656b416363657373436f6e74726f6c3a206d757374206861766520636f60008201527f6c6c656374696f6e20726f6c6500000000000000000000000000000000000000602082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f7b2274726169745f74797065223a20225265706f7369746f7279222c2022766160008201527f6c7565223a220000000000000000000000000000000000000000000000000000602082015250565b7f226e616d65223a22000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b7f22696d616765223a220000000000000000000000000000000000000000000000600082015250565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f7b00000000000000000000000000000000000000000000000000000000000000600082015250565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b7f226f776e6572223a220000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b7f7b2274726169745f74797065223a2022454e53222c202276616c7565223a2200600082015250565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f7b2274726169745f74797065223a2022436f6d6d69742048617368222c20227660008201527f616c7565223a2200000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b7f466c65656b416363657373436f6e74726f6c3a206d757374206861766520746f60008201527f6b656e20726f6c65000000000000000000000000000000000000000000000000602082015250565b61561981614c80565b811461562457600080fd5b50565b61563081614c92565b811461563b57600080fd5b50565b61564781614c9e565b811461565257600080fd5b50565b6002811061566257600080fd5b50565b61566e81614cea565b811461567957600080fd5b5056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa264697066735822122032e73f057e680b3e0d97f7ae6e09c69b55cd4f12df3c5c5724647ab397ebd9d264736f6c63430008070033", - "devdoc": { - "kind": "dev", - "methods": { - "approve(address,uint256)": { - "details": "See {IERC721-approve}." - }, - "balanceOf(address)": { - "details": "See {IERC721-balanceOf}." - }, - "burn(uint256)": { - "details": "Burns a previously minted `tokenId`. May emit a {Transfer} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenOwner` role." - }, - "constructor": { - "details": "Initializes the contract by setting a `name` and a `symbol` to the token collection." - }, - "getApproved(uint256)": { - "details": "See {IERC721-getApproved}." - }, - "getCollectionRoleMembers(uint8)": { - "details": "Returns an array of addresses that all have the collection role." - }, - "getTokenRoleMembers(uint256,uint8)": { - "details": "Returns an array of addresses that all have the same token role for a certain tokenId." - }, - "grantCollectionRole(uint8,address)": { - "details": "Grants the collection role to an address. Requirements: - the caller should have the collection role." - }, - "grantTokenRole(uint256,uint8,address)": { - "details": "Grants the token role to an address. Requirements: - the caller should have the token role." - }, - "hasCollectionRole(uint8,address)": { - "details": "Returns `True` if a certain address has the collection role." - }, - "hasTokenRole(uint256,uint8,address)": { - "details": "Returns `True` if a certain address has the token role." - }, - "isApprovedForAll(address,address)": { - "details": "See {IERC721-isApprovedForAll}." - }, - "mint(address,string,string,string,string,string,string,string)": { - "details": "Mints a token and returns a tokenId. If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event. Requirements: - the caller must have ``collectionOwner``'s admin role." - }, - "name()": { - "details": "See {IERC721Metadata-name}." - }, - "ownerOf(uint256)": { - "details": "See {IERC721-ownerOf}." - }, - "revokeCollectionRole(uint8,address)": { - "details": "Revokes the collection role of an address. Requirements: - the caller should have the collection role." - }, - "revokeTokenRole(uint256,uint8,address)": { - "details": "Revokes the token role of an address. Requirements: - the caller should have the token role." - }, - "safeTransferFrom(address,address,uint256)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "safeTransferFrom(address,address,uint256,bytes)": { - "details": "See {IERC721-safeTransferFrom}." - }, - "setApprovalForAll(address,bool)": { - "details": "See {IERC721-setApprovalForAll}." - }, - "setTokenBuild(uint256,string,string)": { - "details": "Adds a new build to a minted `tokenId`'s builds mapping. May emit a {NewBuild} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role." - }, - "setTokenDescription(uint256,string)": { - "details": "Updates the `description` metadata field of a minted `tokenId`. May emit a {NewTokenDescription} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role." - }, - "setTokenENS(uint256,string)": { - "details": "Updates the `ENS` metadata field of a minted `tokenId`. May emit a {NewTokenENS} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role." - }, - "setTokenExternalURL(uint256,string)": { - "details": "Updates the `externalURL` metadata field of a minted `tokenId`. May emit a {NewTokenExternalURL} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role." - }, - "setTokenImage(uint256,string)": { - "details": "Updates the `image` metadata field of a minted `tokenId`. May emit a {NewTokenImage} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role." - }, - "setTokenName(uint256,string)": { - "details": "Updates the `name` metadata field of a minted `tokenId`. May emit a {NewTokenName} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role." - }, - "supportsInterface(bytes4)": { - "details": "See {IERC165-supportsInterface}." - }, - "symbol()": { - "details": "See {IERC721Metadata-symbol}." - }, - "tokenURI(uint256)": { - "details": "Returns the token metadata associated with the `tokenId`. Returns a based64 encoded string value of the URI. Requirements: - the tokenId must be minted and valid." - }, - "transferFrom(address,address,uint256)": { - "details": "See {IERC721-transferFrom}." - } - }, - "version": 1 - }, - "userdoc": { - "kind": "user", - "methods": {}, - "version": 1 - }, + "bytecode": "0x608060405234801561001057600080fd5b506141ea806100206000396000f3fe6080604052600436106101c25760003560e01c80636352211e116100f7578063aba8112511610095578063cdb0e89e11610064578063cdb0e89e14610510578063e944725014610530578063e985e9c514610550578063f93151771461059957600080fd5b8063aba811251461049d578063b42dbe38146104b0578063b88d4fde146104d0578063c87b56dd146104f057600080fd5b80638c3c0a44116100d15780638c3c0a441461042857806395d89b4114610448578063a22cb4651461045d578063a27d0b271461047d57600080fd5b80636352211e146103bb57806370a08231146103db57806378278cca1461040857600080fd5b80632d957aad116101645780633806f1521161013e5780633806f1521461033b57806342842e0e1461035b57806342966c681461037b5780634cd88b761461039b57600080fd5b80632d957aad146102ce5780632f1e8f0a146102ee578063353b07a41461031b57600080fd5b8063081812fc116101a0578063081812fc14610241578063095ea7b31461026e57806323b872dd1461028e578063246a908b146102ae57600080fd5b806301468deb146101c757806301ffc9a7146101e957806306fdde031461021f575b600080fd5b3480156101d357600080fd5b506101e76101e2366004612aa9565b6105b9565b005b3480156101f557600080fd5b5061020961020436600461296a565b610610565b6040516102169190613de4565b60405180910390f35b34801561022b57600080fd5b50610234610621565b6040516102169190613e00565b34801561024d57600080fd5b5061026161025c366004612a55565b6106b3565b6040516102169190613d81565b34801561027a57600080fd5b506101e7610289366004612937565b6106da565b34801561029a57600080fd5b506101e76102a93660046126fb565b610760565b3480156102ba57600080fd5b506101e76102c9366004612aef565b610791565b3480156102da57600080fd5b506101e76102e93660046129cd565b610844565b3480156102fa57600080fd5b5061030e610309366004612a76565b610887565b6040516102169190613dd3565b34801561032757600080fd5b5061030e6103363660046129ac565b610941565b34801561034757600080fd5b506101e7610356366004612b11565b6109f4565b34801561036757600080fd5b506101e76103763660046126fb565b610b03565b34801561038757600080fd5b506101e7610396366004612a55565b610b1e565b3480156103a757600080fd5b506101e76103b63660046129ef565b610bd8565b3480156103c757600080fd5b506102616103d6366004612a55565b610cb2565b3480156103e757600080fd5b506103fb6103f636600461269d565b610ce7565b6040516102169190613f11565b34801561041457600080fd5b506101e7610423366004612aef565b610d2b565b34801561043457600080fd5b506101e76104433660046129cd565b610dde565b34801561045457600080fd5b50610234610e21565b34801561046957600080fd5b506101e76104783660046127c9565b610e30565b34801561048957600080fd5b506101e7610498366004612aa9565b610e3f565b6103fb6104ab3660046127fc565b610e86565b3480156104bc57600080fd5b506102096104cb366004612aa9565b610fb5565b3480156104dc57600080fd5b506101e76104eb36600461274b565b61102d565b3480156104fc57600080fd5b5061023461050b366004612a55565b611065565b34801561051c57600080fd5b506101e761052b366004612aef565b61127d565b34801561053c57600080fd5b5061020961054b3660046129cd565b61132a565b34801561055c57600080fd5b5061020961056b3660046126be565b6001600160a01b039182166000908152606a6020908152604080832093909416825291909152205460ff1690565b3480156105a557600080fd5b506101e76105b4366004612aef565b61139c565b8260006105c7828233610fb5565b806105d957506105d982600033610fb5565b6105fe5760405162461bcd60e51b81526004016105f590613f01565b60405180910390fd5b61060985858561144f565b5050505050565b600061061b82611508565b92915050565b60606065805461063090614032565b80601f016020809104026020016040519081016040528092919081815260200182805461065c90614032565b80156106a95780601f1061067e576101008083540402835291602001916106a9565b820191906000526020600020905b81548152906001019060200180831161068c57829003601f168201915b5050505050905090565b60006106be82611558565b506000908152606960205260409020546001600160a01b031690565b60006106e582610cb2565b9050806001600160a01b0316836001600160a01b031614156107195760405162461bcd60e51b81526004016105f590613ed1565b336001600160a01b03821614806107355750610735813361056b565b6107515760405162461bcd60e51b81526004016105f590613ee1565b61075b838361158f565b505050565b61076a33826115fd565b6107865760405162461bcd60e51b81526004016105f590613e21565b61075b83838361167c565b81600161079f828233610fb5565b806107b157506107b182600033610fb5565b6107cd5760405162461bcd60e51b81526004016105f590613f01565b6107d684611558565b6000848152609c6020908152604090912084516107fb9260019092019186019061252f565b50604051339061080c908590613282565b6040519081900381209086907fd771eaa1c1382b0a9867125fcd921fdeddd211538b5381353a877abfbe3b50a490600090a450505050565b6000610850813361132a565b80610861575061086160003361132a565b61087d5760405162461bcd60e51b81526004016105f590613e61565b61075b83836117b1565b600082815260996020908152604080832054609a835281842081855290925282206060928460018111156108bd576108bd6140c7565b60018111156108ce576108ce6140c7565b815260200190815260200160002060010180548060200260200160405190810160405280929190818152602001828054801561093357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610915575b505050505091505092915050565b6060600061094e60975490565b6000818152609860205260408120919250846001811115610971576109716140c7565b6001811115610982576109826140c7565b81526020019081526020016000206001018054806020026020016040519081016040528092919081815260200182805480156109e757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116109c9575b5050505050915050919050565b826001610a02828233610fb5565b80610a145750610a1482600033610fb5565b610a305760405162461bcd60e51b81526004016105f590613f01565b610a3985611558565b60408051808201825285815260208082018690526000888152609c90915291822060048101805492936005909201928290610a739061408b565b91829055508152602080820192909252604001600020825180519192610a9e9284929091019061252f565b506020828101518051610ab7926001850192019061252f565b5050604051339150610aca908690613282565b6040519081900381209087907f73b929bf4db6be678cdbc6d41a5fe0a2cbb84ca95572062c4a978d8bd80a41b190600090a45050505050565b61075b8383836040518060200160405280600081525061102d565b806000610b2c828233610fb5565b80610b3e5750610b3e82600033610fb5565b610b5a5760405162461bcd60e51b81526004016105f590613f01565b610b6383611861565b6000838152609c602052604090206002018054610b7f90614032565b15905061075b576000838152609c6020526040812090610b9f82826125b3565b610bad6001830160006125b3565b610bbb6002830160006125b3565b610bc96003830160006125b3565b60048201600090555050505050565b600054610100900460ff1615808015610bf85750600054600160ff909116105b80610c125750303b158015610c12575060005460ff166001145b610c2e5760405162461bcd60e51b81526004016105f590613ea1565b6000805460ff191660011790558015610c51576000805461ff0019166101001790555b610c5b8383611904565b610c63611935565b801561075b576000805461ff00191690556040517f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890610ca590600190613df2565b60405180910390a1505050565b6000818152606760205260408120546001600160a01b03168061061b5760405162461bcd60e51b81526004016105f590613ec1565b60006001600160a01b038216610d0f5760405162461bcd60e51b81526004016105f590613e91565b506001600160a01b031660009081526068602052604090205490565b816001610d39828233610fb5565b80610d4b5750610d4b82600033610fb5565b610d675760405162461bcd60e51b81526004016105f590613f01565b610d7084611558565b6000848152609c602090815260409091208451610d959260039092019186019061252f565b506040513390610da6908590613282565b6040519081900381209086907f91ce7fcd4462481791c3fe849f7049373c5b43ef44aed48e7f1ecce781586e1590600090a450505050565b6000610dea813361132a565b80610dfb5750610dfb60003361132a565b610e175760405162461bcd60e51b81526004016105f590613e61565b61075b8383611969565b60606066805461063090614032565b610e3b3383836119e7565b5050565b826000610e4d828233610fb5565b80610e5f5750610e5f82600033610fb5565b610e7b5760405162461bcd60e51b81526004016105f590613f01565b610609858585611a7d565b600080610e93813361132a565b80610ea45750610ea460003361132a565b610ec05760405162461bcd60e51b81526004016105f590613e61565b6000610ecb609b5490565b9050610ed78a82611b03565b610ee5609b80546001019055565b6000818152609c602090815260409091208a519091610f089183918d019061252f565b508851610f1e90600183019060208c019061252f565b508751610f3490600283019060208b019061252f565b508651610f4a90600383019060208a019061252f565b50600060048201819055604080518082018252888152602080820189905283805260058501815291909220825180519192610f8a9284929091019061252f565b506020828101518051610fa3926001850192019061252f565b50929c9b505050505050505050505050565b600083815260996020908152604080832054609a8352818420818552909252822082856001811115610fe957610fe96140c7565b6001811115610ffa57610ffa6140c7565b8152602080820192909252604090810160009081206001600160a01b038716825290925290205415159150509392505050565b61103733836115fd565b6110535760405162461bcd60e51b81526004016105f590613e21565b61105f84848484611c0c565b50505050565b606061107082611558565b600061107b83610cb2565b6000848152609c6020526040812091925081600181016110a56001600160a01b0386166014611c3f565b846002016111cb8660000180546110bb90614032565b80601f01602080910402602001604051908101604052809291908181526020018280546110e790614032565b80156111345780601f1061110957610100808354040283529160200191611134565b820191906000526020600020905b81548152906001019060200180831161111757829003601f168201915b505050505087600301805461114890614032565b80601f016020809104026020016040519081016040528092919081815260200182805461117490614032565b80156111c15780601f10611196576101008083540402835291602001916111c1565b820191906000526020600020905b8154815290600101906020018083116111a457829003601f168201915b5050505050611db1565b600487015460008181526005890160205260409020600389019160018201906111f390611e3f565b60405160200161120b99989796959493929190613b66565b60408051601f19818403018152828201909152601d82527f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020830152915061125382611edb565b60405160200161126492919061328e565b6040516020818303038152906040529350505050919050565b81600161128b828233610fb5565b8061129d575061129d82600033610fb5565b6112b95760405162461bcd60e51b81526004016105f590613f01565b6112c284611558565b6000848152609c6020908152604090912084516112e19286019061252f565b5060405133906112f2908590613282565b6040519081900381209086907ffbbfca16a2770c7ca6e7063ab1a7eea5fe441ffef818325db51752066a6b128a90600090a450505050565b60008061133660975490565b6000818152609860205260408120919250856001811115611359576113596140c7565b600181111561136a5761136a6140c7565b8152602080820192909252604090810160009081206001600160a01b0387168252909252902054151591505092915050565b8160016113aa828233610fb5565b806113bc57506113bc82600033610fb5565b6113d85760405162461bcd60e51b81526004016105f590613f01565b6113e184611558565b6000848152609c6020908152604090912084516114069260029092019186019061252f565b506040513390611417908590613282565b6040519081900381209086907fedbf1209b3baa7c1b5c43052ce5c511e243b3241d9f67733141d14f1da88cba190600090a450505050565b600083815260996020908152604080832054609a8352818420818552909252822090916114ae9190856001811115611489576114896140c7565b600181111561149a5761149a6140c7565b81526020019081526020016000208361202e565b816001600160a01b03168360018111156114ca576114ca6140c7565b857fe52d746e4c78c98c6bfa291b273406905c3e8550b7d911a6bea686368c2dc79d336040516114fa9190613d81565b60405180910390a450505050565b60006001600160e01b031982166380ac58cd60e01b148061153957506001600160e01b03198216635b5e139f60e01b145b8061061b57506301ffc9a760e01b6001600160e01b031983161461061b565b6000818152606760205260409020546001600160a01b031661158c5760405162461bcd60e51b81526004016105f590613ec1565b50565b600081815260696020526040902080546001600160a01b0319166001600160a01b03841690811790915581906115c482610cb2565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061160983610cb2565b9050806001600160a01b0316846001600160a01b0316148061165057506001600160a01b038082166000908152606a602090815260408083209388168352929052205460ff165b806116745750836001600160a01b0316611669846106b3565b6001600160a01b0316145b949350505050565b826001600160a01b031661168f82610cb2565b6001600160a01b0316146116b55760405162461bcd60e51b81526004016105f590613e41565b6001600160a01b0382166116db5760405162461bcd60e51b81526004016105f590613e71565b6116e88383836001612172565b826001600160a01b03166116fb82610cb2565b6001600160a01b0316146117215760405162461bcd60e51b81526004016105f590613e41565b600081815260696020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260688552838620805460001901905590871680865283862080546001019055868652606790945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60006117bc60975490565b600081815260986020526040812091925061180991908560018111156117e4576117e46140c7565b60018111156117f5576117f56140c7565b8152602001908152602001600020836121f0565b816001600160a01b0316836001811115611825576118256140c7565b7fcf081ed2b728e3115904be00eb8927b2375ff3401839b37f7accfa1bb2bee15c336040516118549190613d81565b60405180910390a3505050565b600061186c82610cb2565b905061187c816000846001612172565b61188582610cb2565b600083815260696020908152604080832080546001600160a01b03199081169091556001600160a01b0385168085526068845282852080546000190190558785526067909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600054610100900460ff1661192b5760405162461bcd60e51b81526004016105f590613ef1565b610e3b8282612253565b600054610100900460ff1661195c5760405162461bcd60e51b81526004016105f590613ef1565b6119676000336117b1565b565b600061197460975490565b600081815260986020526040812091925061199c9190856001811115611489576114896140c7565b816001600160a01b03168360018111156119b8576119b86140c7565b7faeff57f0f5e4d3d10a37d4a70fde8ed67a95e67b251d5c512c0ea98c380d2f95336040516118549190613d81565b816001600160a01b0316836001600160a01b03161415611a195760405162461bcd60e51b81526004016105f590613e81565b6001600160a01b038381166000818152606a602090815260408083209487168084529490915290819020805460ff1916851515179055517f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190611854908590613de4565b600083815260996020908152604080832054609a835281842081855290925282209091611ab791908560018111156117e4576117e46140c7565b816001600160a01b0316836001811115611ad357611ad36140c7565b857f0bf5a13b362503fcc74b8b9b1598aba2f3a9af85d05ba7978f7e9f447f22c239336040516114fa9190613d81565b6001600160a01b038216611b295760405162461bcd60e51b81526004016105f590613eb1565b6000818152606760205260409020546001600160a01b031615611b5e5760405162461bcd60e51b81526004016105f590613e51565b611b6c600083836001612172565b6000818152606760205260409020546001600160a01b031615611ba15760405162461bcd60e51b81526004016105f590613e51565b6001600160a01b038216600081815260686020908152604080832080546001019055848352606790915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b611c1784848461167c565b611c23848484846122a1565b61105f5760405162461bcd60e51b81526004016105f590613e31565b60606000611c4e836002613f91565b611c59906002613f65565b6001600160401b03811115611c7057611c7061411f565b6040519080825280601f01601f191660200182016040528015611c9a576020820181803683370190505b509050600360fc1b81600081518110611cb557611cb5614109565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611ce457611ce4614109565b60200101906001600160f81b031916908160001a9053506000611d08846002613f91565b611d13906001613f65565b90505b6001811115611d8b576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611d4757611d47614109565b1a60f81b828281518110611d5d57611d5d614109565b60200101906001600160f81b031916908160001a90535060049490941c93611d848161401b565b9050611d16565b508315611daa5760405162461bcd60e51b81526004016105f590613e11565b9392505050565b6060611ded60408051808201909152601d81527f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000602082015290565b611e178484604051602001611e039291906132a6565b604051602081830303815290604052611edb565b604051602001611e2892919061328e565b604051602081830303815290604052905092915050565b60606000611e4c836123ae565b60010190506000816001600160401b03811115611e6b57611e6b61411f565b6040519080825280601f01601f191660200182016040528015611e95576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084611ece57611ed3565b611e9f565b509392505050565b6060815160001415611efb57505060408051602081019091526000815290565b60006040518060600160405280604081526020016141756040913990506000600384516002611f2a9190613f65565b611f349190613f7d565b611f3f906004613f91565b6001600160401b03811115611f5657611f5661411f565b6040519080825280601f01601f191660200182016040528015611f80576020820181803683370190505b509050600182016020820185865187015b80821015611fec576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845360018401935050611f91565b5050600386510660018114612008576002811461201b57612023565b603d6001830353603d6002830353612023565b603d60018303535b509195945050505050565b6001600160a01b03811660009081526020839052604090205415610e3b576001600160a01b03811660009081526020839052604081205461207190600190613fb0565b6001848101549192506000916120879190613fb0565b905060008460010182815481106120a0576120a0614109565b6000918252602090912001546001860180546001600160a01b0390921692508291859081106120d1576120d1614109565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055612105836001613f65565b6001600160a01b03821660009081526020879052604090205560018501805480612131576121316140f3565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b038616825286905260408120555050505050565b6001600160a01b0384161580159061219257506001600160a01b03831615155b156121a6576121a18284612486565b6121e4565b6001600160a01b0384166121c0576121a182600085611a7d565b6001600160a01b0383166121e4576000828152609960205260409020805460010190555b61105f848484846124a7565b6001600160a01b038116600090815260208390526040902054610e3b576001828101805491820181556000818152602080822090930180546001600160a01b0319166001600160a01b039590951694851790559054928152929052604090912055565b600054610100900460ff1661227a5760405162461bcd60e51b81526004016105f590613ef1565b815161228d90606590602085019061252f565b50805161075b90606690602084019061252f565b60006001600160a01b0384163b156123a357604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906122e5903390899088908890600401613d8f565b602060405180830381600087803b1580156122ff57600080fd5b505af192505050801561232f575060408051601f3d908101601f1916820190925261232c9181019061298b565b60015b612389573d80801561235d576040519150601f19603f3d011682016040523d82523d6000602084013e612362565b606091505b5080516123815760405162461bcd60e51b81526004016105f590613e31565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611674565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106123ed5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310612419576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061243757662386f26fc10000830492506010015b6305f5e100831061244f576305f5e100830492506008015b612710831061246357612710830492506004015b60648310612475576064830492506002015b600a831061061b5760010192915050565b600082815260996020526040902080546001019055610e3b82600083611a7d565b600181111561105f576001600160a01b038416156124ed576001600160a01b038416600090815260686020526040812080548392906124e7908490613fb0565b90915550505b6001600160a01b0383161561105f576001600160a01b03831660009081526068602052604081208054839290612524908490613f65565b909155505050505050565b82805461253b90614032565b90600052602060002090601f01602090048101928261255d57600085556125a3565b82601f1061257657805160ff19168380011785556125a3565b828001600101855582156125a3579182015b828111156125a3578251825591602001919060010190612588565b506125af9291506125e9565b5090565b5080546125bf90614032565b6000825580601f106125cf575050565b601f01602090049060005260206000209081019061158c91905b5b808211156125af57600081556001016125ea565b600061261161260c84613f3b565b613f1f565b90508281526020810184848401111561262c5761262c600080fd5b611ed3848285613fe3565b803561061b81614135565b803561061b81614149565b803561061b81614151565b805161061b81614151565b600082601f83011261267757612677600080fd5b81356116748482602086016125fe565b803561061b81614161565b803561061b8161416e565b6000602082840312156126b2576126b2600080fd5b60006116748484612637565b600080604083850312156126d4576126d4600080fd5b60006126e08585612637565b92505060206126f185828601612637565b9150509250929050565b60008060006060848603121561271357612713600080fd5b600061271f8686612637565b935050602061273086828701612637565b925050604061274186828701612692565b9150509250925092565b6000806000806080858703121561276457612764600080fd5b60006127708787612637565b945050602061278187828801612637565b935050604061279287828801612692565b92505060608501356001600160401b038111156127b1576127b1600080fd5b6127bd87828801612663565b91505092959194509250565b600080604083850312156127df576127df600080fd5b60006127eb8585612637565b92505060206126f185828601612642565b600080600080600080600060e0888a03121561281a5761281a600080fd5b60006128268a8a612637565b97505060208801356001600160401b0381111561284557612845600080fd5b6128518a828b01612663565b96505060408801356001600160401b0381111561287057612870600080fd5b61287c8a828b01612663565b95505060608801356001600160401b0381111561289b5761289b600080fd5b6128a78a828b01612663565b94505060808801356001600160401b038111156128c6576128c6600080fd5b6128d28a828b01612663565b93505060a08801356001600160401b038111156128f1576128f1600080fd5b6128fd8a828b01612663565b92505060c08801356001600160401b0381111561291c5761291c600080fd5b6129288a828b01612663565b91505092959891949750929550565b6000806040838503121561294d5761294d600080fd5b60006129598585612637565b92505060206126f185828601612692565b60006020828403121561297f5761297f600080fd5b6000611674848461264d565b6000602082840312156129a0576129a0600080fd5b60006116748484612658565b6000602082840312156129c1576129c1600080fd5b60006116748484612687565b600080604083850312156129e3576129e3600080fd5b60006126e08585612687565b60008060408385031215612a0557612a05600080fd5b82356001600160401b03811115612a1e57612a1e600080fd5b612a2a85828601612663565b92505060208301356001600160401b03811115612a4957612a49600080fd5b6126f185828601612663565b600060208284031215612a6a57612a6a600080fd5b60006116748484612692565b60008060408385031215612a8c57612a8c600080fd5b6000612a988585612692565b92505060206126f185828601612687565b600080600060608486031215612ac157612ac1600080fd5b6000612acd8686612692565b9350506020612ade86828701612687565b925050604061274186828701612637565b60008060408385031215612b0557612b05600080fd5b6000612a2a8585612692565b600080600060608486031215612b2957612b29600080fd5b6000612b358686612692565b93505060208401356001600160401b03811115612b5457612b54600080fd5b612b6086828701612663565b92505060408401356001600160401b03811115612b7f57612b7f600080fd5b61274186828701612663565b6000612b978383612b9f565b505060200190565b612ba881613fc7565b82525050565b6000612bb8825190565b80845260209384019383018060005b83811015612bec578151612bdb8882612b8b565b975060208301925050600101612bc7565b509495945050505050565b801515612ba8565b6000612c09825190565b808452602084019350612c20818560208601613fef565b601f01601f19169290920192915050565b612ba881613fd8565b6000612c44825190565b612c52818560208601613fef565b9290920192915050565b60008154612c6981614032565b600182168015612c805760018114612c9157612cc1565b60ff19831686528186019350612cc1565b60008581526020902060005b83811015612cb957815488820152600190910190602001612c9d565b838801955050505b50505092915050565b60208082527f537472696e67733a20686578206c656e67746820696e73756666696369656e74910190815260005b5060200190565b602d81526000602082017f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6581526c1c881bdc88185c1c1c9bdd9959609a1b602082015291505b5060400190565b6e1e17ba39b830b71f1e17ba32bc3a1f60891b815260005b50600f0190565b603281526000602082017f4552433732313a207472616e7366657220746f206e6f6e20455243373231526581527131b2b4bb32b91034b6b83632b6b2b73a32b960711b60208201529150612d45565b6e113232b9b1b934b83a34b7b7111d1160891b81526000612d64565b61088b60f21b815260005b5060020190565b602581526000602082017f4552433732313a207472616e736665722066726f6d20696e636f72726563742081526437bbb732b960d91b60208201529150612d45565b601c81526000602082017f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000081529150612cf8565b602d81526000602082017f466c65656b416363657373436f6e74726f6c3a206d757374206861766520636f81526c6c6c656374696f6e20726f6c6560981b60208201529150612d45565b602481526000602082017f4552433732313a207472616e7366657220746f20746865207a65726f206164648152637265737360e01b60208201529150612d45565b601981526000602082017f4552433732313a20617070726f766520746f2063616c6c65720000000000000081529150612cf8565b602981526000602082017f4552433732313a2061646472657373207a65726f206973206e6f7420612076618152683634b21037bbb732b960b91b60208201529150612d45565b602e81526000602082017f496e697469616c697a61626c653a20636f6e747261637420697320616c72656181526d191e481a5b9a5d1a585b1a5e995960921b60208201529150612d45565b681134b6b0b3b2911d1160b91b815260005b5060090190565b61227d60f01b81526000612de1565b60208082527f4552433732313a206d696e7420746f20746865207a65726f206164647265737391019081526000612cf8565b607d60f81b815260005b5060010190565b607b60f81b81526000613012565b6e2261747472696275746573223a205b60881b81526000612d64565b681137bbb732b9111d1160b91b81526000612fc0565b601881526000602082017f4552433732313a20696e76616c696420746f6b656e204944000000000000000081529150612cf8565b605d60f81b81526000613012565b602181526000602082017f4552433732313a20617070726f76616c20746f2063757272656e74206f776e658152603960f91b60208201529150612d45565b7f3c67207472616e73666f726d3d226d617472697828312030203020312033303281527410191b18971a1b94911039ba3cb6329e911110101f60591b602082015260005b5060350190565b603d81526000602082017f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f81527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c00000060208201529150612d45565b651e3232b3399f60d11b815260005b5060060190565b7f3c67207472616e73666f726d3d226d617472697828332e34322030203020332e8152741a1910199818171c9c10191a99171c9c149110101f60591b6020820152600061311d565b602b81526000602082017f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206981526a6e697469616c697a696e6760a81b60208201529150612d45565b602881526000602082017f466c65656b416363657373436f6e74726f6c3a206d757374206861766520746f8152676b656e20726f6c6560c01b60208201529150612d45565b651e17b9bb339f60d11b8152600061318d565b80612ba8565b6000611daa8284612c3a565b600061329a8285612c3a565b91506116748284612c3a565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f7376672220786d6c6e733a786c696e6b3d22687474703a2f2f7777772e60208201527f77332e6f72672f313939392f786c696e6b222076657273696f6e3d22312e312260408201527f2077696474683d2236343022206865696768743d22343830222076696577426f60608201527f783d2230203020363430203438302220786d6c3a73706163653d227072657365608082015264393b32911f60d91b60a082015260a501600061337d8261317e565b661e17b232b3399f60c91b8152600701915061339882613194565b7f3c706f6c79676f6e207374796c653d227374726f6b653a2072676228302c302c81527f30293b207374726f6b652d77696474683a20383b207374726f6b652d6461736860208201527f61727261793a206e6f6e653b207374726f6b652d6c696e656361703a2062757460408201527f743b207374726f6b652d646173686f66667365743a20303b207374726f6b652d60608201527f6c696e656a6f696e3a206d697465723b207374726f6b652d6d697465726c696d60808201527f69743a20343b2066696c6c3a20726762283135322c3135322c313833293b206660a08201527f696c6c2d72756c653a206e6f6e7a65726f3b206f7061636974793a20313b222060c08201527f766563746f722d6566666563743d226e6f6e2d7363616c696e672d7374726f6b60e08201527f65222020706f696e74733d222d35302c2d3530202d35302c35302035302c35306101008201526b101a9816169a98101110179f60a11b610120820152631e17b39f60e11b61012c82018190527f3c67207472616e73666f726d3d226d61747269782831203020302031203330336101308301527f2e35203131352e36372922207374796c653d222220203e0000000000000000006101508301527f3c7465787420786d6c3a73706163653d2270726573657276652220666f6e742d6101678301527f66616d696c793d224f70656e2053616e732220666f6e742d73697a653d2232346101878301527f2220666f6e742d7374796c653d226e6f726d616c2220666f6e742d77656967686101a78301527f743d226e6f726d616c22207374796c653d227374726f6b653a206e6f6e653b206101c78301527f7374726f6b652d77696474683a20313b207374726f6b652d64617368617272616101e78301527f793a206e6f6e653b207374726f6b652d6c696e656361703a20627574743b20736102078301527f74726f6b652d646173686f66667365743a20303b207374726f6b652d6c696e656102278301527f6a6f696e3a206d697465723b207374726f6b652d6d697465726c696d69743a206102478301527f343b2066696c6c3a2072676228302c302c30293b2066696c6c2d72756c653a206102678301527f6e6f6e7a65726f3b206f7061636974793a20313b2077686974652d73706163656102878301527f3a207072653b22203e3c747370616e20783d222d34352e372220793d22352e366102a78301527f3522207374796c653d227374726f6b652d77696474683a20313b20666f6e742d6102c78301527f66616d696c793a20224f70656e2053616e73222c2073616e732d73657269663b6102e78301527f20666f6e742d73697a653a20313870783b20666f6e742d7374796c653a206e6f6103078301527f726d616c3b20666f6e742d7765696768743a206e6f726d616c3b2066696c6c3a6103278301527f2072676228302c302c30293b20223e466c65656b204e4641733c2f747370616e610347830152671f1e17ba32bc3a1f60c11b61036783015261036f8201526103730191506137f7826130d9565b7f3c7465787420786d6c3a73706163653d2270726573657276652220666f6e742d81527f66616d696c793d224f70656e2053616e732220666f6e742d73697a653d22323860208201527f2220666f6e742d7374796c653d226e6f726d616c2220666f6e742d776569676860408201527f743d226e6f726d616c22207374796c653d227374726f6b653a206e6f6e653b2060608201527f7374726f6b652d77696474683a20313b207374726f6b652d646173686172726160808201527f793a206e6f6e653b207374726f6b652d6c696e656361703a20627574743b207360a08201527f74726f6b652d646173686f66667365743a20303b207374726f6b652d6c696e6560c08201527f6a6f696e3a206d697465723b207374726f6b652d6d697465726c696d69743a2060e08201527f343b2066696c6c3a2072676228302c302c30293b2066696c6c2d72756c653a206101008201527f6e6f6e7a65726f3b206f7061636974793a20313b2077686974652d73706163656101208201527f3a207072653b22203e3c747370616e20783d222d34342e32362220793d222d366101408201527f2e313422207374796c653d227374726f6b652d77696474683a20313b20666f6e6101608201527f742d66616d696c793a20224f70656e2053616e73222c2073616e732d736572696101808201527f663b20666f6e742d73697a653a20313870783b20666f6e742d7374796c653a206101a08201527f6e6f726d616c3b20666f6e742d7765696768743a206e6f726d616c3b2066696c6101c082015270361d103933b1141816181618149d90111f60791b6101e08201526101f1019150613a608285612c3a565b7f3c2f747370616e3e3c747370616e20783d222d33372e31342220793d2231372e81527f343522207374796c653d227374726f6b652d77696474683a20313b20666f6e7460208201527f2d66616d696c793a20224f70656e2053616e73222c2073616e732d736572696660408201527f3b20666f6e742d73697a653a20313870783b20666f6e742d7374796c653a206e60608201527f6f726d616c3b20666f6e742d7765696768743a206e6f726d616c3b2066696c6c60808201526f1d103933b1141816181618149d90111f60811b60a082015260b0019150613b438284612c3a565b9150613b4e82612d4c565b631e17b39f60e11b8152600401915061167482613269565b6000613b7182613019565b67113730b6b2911d1160c11b81526008019150613b8e828c612c5c565b9150613b9982612dd6565b9150613ba482612dba565b9150613bb0828b612c5c565b9150613bbb82612dd6565b9150613bc682613043565b9150613bd2828a612c3a565b9150613bdd82612dd6565b6f1132bc3a32b93730b62fbab936111d1160811b81526010019150613c028289612c5c565b9150613c0d82612dd6565b9150613c1882612fae565b9150613c248288612c3a565b9150613c2f82612dd6565b9150613c3a82613027565b7f7b2274726169745f74797065223a2022454e53222c202276616c7565223a22008152601f019150613c6c8287612c5c565b62089f4b60ea1b81527f7b2274726169745f74797065223a2022436f6d6d69742048617368222c20227660038201526630b63ab2911d1160c91b6023820152602a019150613cba8286612c5c565b62089f4b60ea1b81527f7b2274726169745f74797065223a20225265706f7369746f7279222c20227661600382015265363ab2911d1160d11b60238201526029019150613d078285612c5c565b62089f4b60ea1b81527f7b2274726169745f74797065223a202256657273696f6e222c202276616c7565600382015262111d1160e91b60238201526026019150613d518284612c3a565b9150613d5c82612fc7565b9150613d678261308d565b9150613d7282613008565b9b9a5050505050505050505050565b6020810161061b8284612b9f565b60808101613d9d8287612b9f565b613daa6020830186612b9f565b613db7604083018561327c565b8181036060830152613dc98184612bff565b9695505050505050565b60208082528101611daa8184612bae565b6020810161061b8284612bf7565b6020810161061b8284612c31565b60208082528101611daa8184612bff565b6020808252810161061b81612cca565b6020808252810161061b81612cff565b6020808252810161061b81612d6b565b6020808252810161061b81612de8565b6020808252810161061b81612e2a565b6020808252810161061b81612e5e565b6020808252810161061b81612ea8565b6020808252810161061b81612ee9565b6020808252810161061b81612f1d565b6020808252810161061b81612f63565b6020808252810161061b81612fd6565b6020808252810161061b81613059565b6020808252810161061b8161309b565b6020808252810161061b81613124565b6020808252810161061b816131dc565b6020808252810161061b81613224565b6020810161061b828461327c565b6000613f2a60405190565b9050613f36828261405f565b919050565b60006001600160401b03821115613f5457613f5461411f565b601f19601f83011660200192915050565b60008219821115613f7857613f7861409b565b500190565b600082613f8c57613f8c6140b1565b500490565b6000816000190483118215151615613fab57613fab61409b565b500290565b600082821015613fc257613fc261409b565b500390565b60006001600160a01b03821661061b565b600060ff821661061b565b82818337506000910152565b60005b8381101561400a578181015183820152602001613ff2565b8381111561105f5750506000910152565b60008161402a5761402a61409b565b506000190190565b60028104600182168061404657607f821691505b60208210811415614059576140596140dd565b50919050565b601f19601f83011681018181106001600160401b03821117156140845761408461411f565b6040525050565b6000600019821415613012576130125b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61413e81613fc7565b811461158c57600080fd5b80151561413e565b6001600160e01b0319811661413e565b6002811061158c57600080fd5b8061413e56fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa2646970667358221220b134b709d6db06d03e23b6b163ce704738e195c692f6b8aaf48a6a6471fc951164736f6c63430008070033", + "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"CollectionRoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"CollectionRoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"commitHash\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewBuild\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenDescription\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"ENS\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenENS\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"externalURL\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenExternalURL\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"image\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenImage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"token\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"triggeredBy\",\"type\":\"address\"}],\"name\":\"NewTokenName\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"TokenRoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"byAddress\",\"type\":\"address\"}],\"name\":\"TokenRoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"}],\"name\":\"getCollectionRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"}],\"name\":\"getTokenRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantCollectionRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantTokenRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasCollectionRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasTokenRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbol\",\"type\":\"string\"}],\"name\":\"initialize\",\"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\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"externalURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"ENS\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"commitHash\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"gitRepository\",\"type\":\"string\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeCollectionRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"enum FleekAccessControl.Roles\",\"name\":\"role\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeTokenRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_commitHash\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_gitRepository\",\"type\":\"string\"}],\"name\":\"setTokenBuild\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenDescription\",\"type\":\"string\"}],\"name\":\"setTokenDescription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenENS\",\"type\":\"string\"}],\"name\":\"setTokenENS\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenExternalURL\",\"type\":\"string\"}],\"name\":\"setTokenExternalURL\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_tokenName\",\"type\":\"string\"}],\"name\":\"setTokenName\",\"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\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"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\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"See {IERC721-approve}.\"},\"balanceOf(address)\":{\"details\":\"See {IERC721-balanceOf}.\"},\"burn(uint256)\":{\"details\":\"Burns a previously minted `tokenId`. May emit a {Transfer} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenOwner` role.\"},\"getApproved(uint256)\":{\"details\":\"See {IERC721-getApproved}.\"},\"getCollectionRoleMembers(uint8)\":{\"details\":\"Returns an array of addresses that all have the collection role.\"},\"getTokenRoleMembers(uint256,uint8)\":{\"details\":\"Returns an array of addresses that all have the same token role for a certain tokenId.\"},\"grantCollectionRole(uint8,address)\":{\"details\":\"Grants the collection role to an address. Requirements: - the caller should have the collection role.\"},\"grantTokenRole(uint256,uint8,address)\":{\"details\":\"Grants the token role to an address. Requirements: - the caller should have the token role.\"},\"hasCollectionRole(uint8,address)\":{\"details\":\"Returns `True` if a certain address has the collection role.\"},\"hasTokenRole(uint256,uint8,address)\":{\"details\":\"Returns `True` if a certain address has the token role.\"},\"initialize(string,string)\":{\"details\":\"Initializes the contract by setting a `name` and a `symbol` to the token collection.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC721-isApprovedForAll}.\"},\"mint(address,string,string,string,string,string,string)\":{\"details\":\"Mints a token and returns a tokenId. If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event. Requirements: - the caller must have ``collectionOwner``'s admin role.\"},\"name()\":{\"details\":\"See {IERC721Metadata-name}.\"},\"ownerOf(uint256)\":{\"details\":\"See {IERC721-ownerOf}.\"},\"revokeCollectionRole(uint8,address)\":{\"details\":\"Revokes the collection role of an address. Requirements: - the caller should have the collection role.\"},\"revokeTokenRole(uint256,uint8,address)\":{\"details\":\"Revokes the token role of an address. Requirements: - the caller should have the token role.\"},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC721-setApprovalForAll}.\"},\"setTokenBuild(uint256,string,string)\":{\"details\":\"Adds a new build to a minted `tokenId`'s builds mapping. May emit a {NewBuild} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenDescription(uint256,string)\":{\"details\":\"Updates the `description` metadata field of a minted `tokenId`. May emit a {NewTokenDescription} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenENS(uint256,string)\":{\"details\":\"Updates the `ENS` metadata field of a minted `tokenId`. May emit a {NewTokenENS} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenExternalURL(uint256,string)\":{\"details\":\"Updates the `externalURL` metadata field of a minted `tokenId`. May emit a {NewTokenExternalURL} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"setTokenName(uint256,string)\":{\"details\":\"Updates the `name` metadata field of a minted `tokenId`. May emit a {NewTokenName} event. Requirements: - the tokenId must be minted and valid. - the sender must have the `tokenController` role.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}.\"},\"symbol()\":{\"details\":\"See {IERC721Metadata-symbol}.\"},\"tokenURI(uint256)\":{\"details\":\"Returns the token metadata associated with the `tokenId`. Returns a based64 encoded string value of the URI. Requirements: - the tokenId must be minted and valid.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-transferFrom}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/FleekERC721.sol\":\"FleekERC721\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":true,\"cse\":true,\"deduplicate\":true,\"inliner\":true,\"jumpdestRemover\":true,\"orderLiterals\":true,\"peephole\":true,\"yul\":false},\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0xe798cadb41e2da274913e4b3183a80f50fb057a42238fe8467e077268100ec27\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://899f850f7df5a270bccfb765d70069959ca1c20d3a7381c1c3bda8a3ffee1935\",\"dweb:/ipfs/QmVdnAqwyX2L3nX2HDA5WKGtVBFyH1nKE9A1k7fZnPBkhP\"]},\"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\":{\"keccak256\":\"0x2a6a0b9fd2d316dcb4141159a9d13be92654066d6c0ae92757ed908ecdfecff0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c05d9be7ee043009eb9f2089b452efc0961345531fc63354a249d7337c69f3bb\",\"dweb:/ipfs/QmTXhzgaYrh6og76BP85i6exNFAv5NYw64uVWyworNogyG\"]},\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol\":{\"keccak256\":\"0xbb2ed8106d94aeae6858e2551a1e7174df73994b77b13ebd120ccaaef80155f5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8bc3c6a456dba727d8dd9fd33420febede490abb49a07469f61d2a3ace66a95a\",\"dweb:/ipfs/QmVAWtEVj7K5AbvgJa9Dz22KiDq9eoptCjnVZqsTMtKXyd\"]},\"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\":{\"keccak256\":\"0x2c0b89cef83f353c6f9488c013d8a5968587ffdd6dfc26aad53774214b97e229\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4a68e662c2a82412308b1feb24f3d61a44b3b8772f44cbd440446237313c3195\",\"dweb:/ipfs/QmfBuWUE2TQef9hghDzzuVkDskw3UGAyPgLmPifTNV7K6g\"]},\"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol\":{\"keccak256\":\"0x95a471796eb5f030fdc438660bebec121ad5d063763e64d92376ffb4b5ce8b70\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ffbd627e6958983d288801acdedbf3491ee0ebf1a430338bce47c96481ce9e3\",\"dweb:/ipfs/QmUM1vpmNgBV34sYf946SthDJNGhwwqjoRggmj4TUUQmdB\"]},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x2edcb41c121abc510932e8d83ff8b82cf9cdde35e7c297622f5c29ef0af25183\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://72460c66cd1c3b1c11b863e0d8df0a1c56f37743019e468dc312c754f43e3b06\",\"dweb:/ipfs/QmPExYKiNb9PUsgktQBupPaM33kzDHxaYoVeJdLhv8s879\"]},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\":{\"keccak256\":\"0x6b9a5d35b744b25529a2856a8093e7c03fb35a34b1c4fb5499e560f8ade140da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://187b5c3a1c9e77678732a2cc5284237f9cfca6bc28ee8bc0a0f4f951d7b3a2f8\",\"dweb:/ipfs/Qmb2KFr7WuQu7btdCiftQG64vTzrG4UyzVmo53EYHcnHYA\"]},\"@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol\":{\"keccak256\":\"0x9a3b990bd56d139df3e454a9edf1c64668530b5a77fc32eb063bc206f958274a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0895399d170daab2d69b4c43a0202e5a07f2e67a93b26e3354dcbedb062232f7\",\"dweb:/ipfs/QmUM1VH3XDk559Dsgh4QPvupr3YVKjz87HrSyYzzVFZbxw\"]},\"@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol\":{\"keccak256\":\"0xc6cef87559d0aeffdf0a99803de655938a7779ec0a3cd5d4383483ad85565a09\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://92ad7e572cf44e6b4b37631b44b62f9eb9fb1cf14d9ce51c1504d5dc7ccaf758\",\"dweb:/ipfs/QmcnbqX85tsWnUXPmtuPLE4SczME2sJaTfmqEFkuAJvWhy\"]},\"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\":{\"keccak256\":\"0xc1bd5b53319c68f84e3becd75694d941e8f4be94049903232cd8bc7c535aaa5a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://056027a78e6f4b78a39be530983551651ee5a052e786ca2c1c6a3bb1222b03b4\",\"dweb:/ipfs/QmXRUpywAqNwAfXS89vrtiE2THRM9dX9pQ4QxAkV1Wx9kt\"]},\"@openzeppelin/contracts/utils/Base64.sol\":{\"keccak256\":\"0x5f3461639fe20794cfb4db4a6d8477388a15b2e70a018043084b7c4bedfa8136\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://77e5309e2cc4cdc3395214edb0ff43ff5a5f7373f5a425383e540f6fab530f96\",\"dweb:/ipfs/QmTV8DZ9knJDa3b5NPBFQqjvTzodyZVjRUg5mx5A99JPLJ\"]},\"@openzeppelin/contracts/utils/Counters.sol\":{\"keccak256\":\"0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://59e1c62884d55b70f3ae5432b44bb3166ad71ae3acd19c57ab6ddc3c87c325ee\",\"dweb:/ipfs/QmezuXg5GK5oeA4F91EZhozBFekhq5TD966bHPH18cCqhu\"]},\"@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8c969013129ba9e651a20735ef659fef6d8a1139ea3607bd4b26ddea2d645634\",\"dweb:/ipfs/QmVhVa6LGuzAcB8qgDtVHRkucn4ihj5UZr8xBLcJkP6ucb\"]},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://33bbf48cc069be677705037ba7520c22b1b622c23b33e1a71495f2d36549d40b\",\"dweb:/ipfs/Qmct36zWXv3j7LZB83uwbg7TXwnZSN1fqHNDZ93GG98bGz\"]},\"contracts/FleekAccessControl.sol\":{\"keccak256\":\"0x99b148a767f42ff1bfcee7ff68d8b11ece6aa78a96a5637c9b5e1ddc1cca7b34\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ff6dd367c0f3894c2c3fcd28cd02ccce384bea6dc23baa7b03041be237cc64ae\",\"dweb:/ipfs/QmWGtcukpo1ApXiVxkAfMJ3u8Be9quLXBzExcXr6KJ4gmL\"]},\"contracts/FleekERC721.sol\":{\"keccak256\":\"0x34e2da162e73cedb56c5fedc413604a79446535c2a16c2212b562c78a911241c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3d184d08e7803189d6f8091135d3550d1d528cadad0c6f52c973cc45a0260bc0\",\"dweb:/ipfs/Qma3FAvNVf6EQUqV1fdEZ126ZUQRttSSMEX3m9o4jqfHVW\"]}},\"version\":1}", "storageLayout": { "storage": [ { - "astId": 25, + "astId": 6, + "contract": "contracts/FleekERC721.sol:FleekERC721", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 9, + "contract": "contracts/FleekERC721.sol:FleekERC721", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 1624, + "contract": "contracts/FleekERC721.sol:FleekERC721", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 1843, + "contract": "contracts/FleekERC721.sol:FleekERC721", + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 197, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_name", "offset": 0, - "slot": "0", + "slot": "101", "type": "t_string_storage" }, { - "astId": 27, + "astId": 199, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_symbol", "offset": 0, - "slot": "1", + "slot": "102", "type": "t_string_storage" }, { - "astId": 31, + "astId": 203, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_owners", "offset": 0, - "slot": "2", + "slot": "103", "type": "t_mapping(t_uint256,t_address)" }, { - "astId": 35, + "astId": 207, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_balances", "offset": 0, - "slot": "3", + "slot": "104", "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 39, + "astId": 211, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_tokenApprovals", "offset": 0, - "slot": "4", + "slot": "105", "type": "t_mapping(t_uint256,t_address)" }, { - "astId": 45, + "astId": 217, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_operatorApprovals", "offset": 0, - "slot": "5", + "slot": "106", "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2715, + "astId": 1137, + "contract": "contracts/FleekERC721.sol:FleekERC721", + "label": "__gap", + "offset": 0, + "slot": "107", + "type": "t_array(t_uint256)44_storage" + }, + { + "astId": 3946, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_collectionRolesVersion", "offset": 0, - "slot": "6", - "type": "t_struct(Counter)1510_storage" + "slot": "151", + "type": "t_struct(Counter)2774_storage" }, { - "astId": 2723, + "astId": 3954, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_collectionRoles", "offset": 0, - "slot": "7", - "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage))" + "slot": "152", + "type": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))" }, { - "astId": 2728, + "astId": 3959, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_tokenRolesVersion", "offset": 0, - "slot": "8", - "type": "t_mapping(t_uint256,t_struct(Counter)1510_storage)" + "slot": "153", + "type": "t_mapping(t_uint256,t_struct(Counter)2774_storage)" }, { - "astId": 2738, + "astId": 3969, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_tokenRoles", "offset": 0, - "slot": "9", - "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage)))" + "slot": "154", + "type": "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))" }, { - "astId": 3380, + "astId": 4614, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_tokenIds", "offset": 0, - "slot": "10", - "type": "t_struct(Counter)1510_storage" + "slot": "155", + "type": "t_struct(Counter)2774_storage" }, { - "astId": 3385, + "astId": 4619, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_apps", "offset": 0, - "slot": "11", - "type": "t_mapping(t_uint256,t_struct(App)3372_storage)" + "slot": "156", + "type": "t_mapping(t_uint256,t_struct(App)4606_storage)" } ], "types": { @@ -1232,12 +1116,24 @@ "label": "address[]", "numberOfBytes": "32" }, + "t_array(t_uint256)44_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[44]", + "numberOfBytes": "1408" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, "t_bool": { "encoding": "inplace", "label": "bool", "numberOfBytes": "1" }, - "t_enum(Roles)2664": { + "t_enum(Roles)3895": { "encoding": "inplace", "label": "enum FleekAccessControl.Roles", "numberOfBytes": "1" @@ -1263,12 +1159,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage)": { + "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)": { "encoding": "mapping", - "key": "t_enum(Roles)2664", + "key": "t_enum(Roles)3895", "label": "mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)", "numberOfBytes": "32", - "value": "t_struct(Role)2712_storage" + "value": "t_struct(Role)3943_storage" }, "t_mapping(t_uint256,t_address)": { "encoding": "mapping", @@ -1277,52 +1173,52 @@ "numberOfBytes": "32", "value": "t_address" }, - "t_mapping(t_uint256,t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage))": { + "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role))", "numberOfBytes": "32", - "value": "t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage)" + "value": "t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)" }, - "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage)))": { + "t_mapping(t_uint256,t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage)))": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => mapping(uint256 => mapping(enum FleekAccessControl.Roles => struct FleekAccessControl.Role)))", "numberOfBytes": "32", - "value": "t_mapping(t_uint256,t_mapping(t_enum(Roles)2664,t_struct(Role)2712_storage))" + "value": "t_mapping(t_uint256,t_mapping(t_enum(Roles)3895,t_struct(Role)3943_storage))" }, - "t_mapping(t_uint256,t_struct(App)3372_storage)": { + "t_mapping(t_uint256,t_struct(App)4606_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct FleekERC721.App)", "numberOfBytes": "32", - "value": "t_struct(App)3372_storage" + "value": "t_struct(App)4606_storage" }, - "t_mapping(t_uint256,t_struct(Build)3377_storage)": { + "t_mapping(t_uint256,t_struct(Build)4611_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct FleekERC721.Build)", "numberOfBytes": "32", - "value": "t_struct(Build)3377_storage" + "value": "t_struct(Build)4611_storage" }, - "t_mapping(t_uint256,t_struct(Counter)1510_storage)": { + "t_mapping(t_uint256,t_struct(Counter)2774_storage)": { "encoding": "mapping", "key": "t_uint256", "label": "mapping(uint256 => struct Counters.Counter)", "numberOfBytes": "32", - "value": "t_struct(Counter)1510_storage" + "value": "t_struct(Counter)2774_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(App)3372_storage": { + "t_struct(App)4606_storage": { "encoding": "inplace", "label": "struct FleekERC721.App", "members": [ { - "astId": 3356, + "astId": 4592, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "name", "offset": 0, @@ -1330,7 +1226,7 @@ "type": "t_string_storage" }, { - "astId": 3358, + "astId": 4594, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "description", "offset": 0, @@ -1338,54 +1234,46 @@ "type": "t_string_storage" }, { - "astId": 3360, + "astId": 4596, "contract": "contracts/FleekERC721.sol:FleekERC721", - "label": "image", + "label": "externalURL", "offset": 0, "slot": "2", "type": "t_string_storage" }, { - "astId": 3362, + "astId": 4598, "contract": "contracts/FleekERC721.sol:FleekERC721", - "label": "externalURL", + "label": "ENS", "offset": 0, "slot": "3", "type": "t_string_storage" }, { - "astId": 3364, - "contract": "contracts/FleekERC721.sol:FleekERC721", - "label": "ENS", - "offset": 0, - "slot": "4", - "type": "t_string_storage" - }, - { - "astId": 3366, + "astId": 4600, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "currentBuild", "offset": 0, - "slot": "5", + "slot": "4", "type": "t_uint256" }, { - "astId": 3371, + "astId": 4605, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "builds", "offset": 0, - "slot": "6", - "type": "t_mapping(t_uint256,t_struct(Build)3377_storage)" + "slot": "5", + "type": "t_mapping(t_uint256,t_struct(Build)4611_storage)" } ], - "numberOfBytes": "224" + "numberOfBytes": "192" }, - "t_struct(Build)3377_storage": { + "t_struct(Build)4611_storage": { "encoding": "inplace", "label": "struct FleekERC721.Build", "members": [ { - "astId": 3374, + "astId": 4608, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "commitHash", "offset": 0, @@ -1393,7 +1281,7 @@ "type": "t_string_storage" }, { - "astId": 3376, + "astId": 4610, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "gitRepository", "offset": 0, @@ -1403,12 +1291,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Counter)1510_storage": { + "t_struct(Counter)2774_storage": { "encoding": "inplace", "label": "struct Counters.Counter", "members": [ { - "astId": 1509, + "astId": 2773, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "_value", "offset": 0, @@ -1418,12 +1306,12 @@ ], "numberOfBytes": "32" }, - "t_struct(Role)2712_storage": { + "t_struct(Role)3943_storage": { "encoding": "inplace", "label": "struct FleekAccessControl.Role", "members": [ { - "astId": 2708, + "astId": 3939, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "indexes", "offset": 0, @@ -1431,7 +1319,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 2711, + "astId": 3942, "contract": "contracts/FleekERC721.sol:FleekERC721", "label": "members", "offset": 0, @@ -1445,6 +1333,11 @@ "encoding": "inplace", "label": "uint256", "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" } } } diff --git a/deployments/mumbai/proxy.json b/deployments/mumbai/proxy.json new file mode 100644 index 0000000..c59d28f --- /dev/null +++ b/deployments/mumbai/proxy.json @@ -0,0 +1,12 @@ +{ + "FleekERC721": [ + { + "address": "0x21d7fBe220958A0F0f7cAE58780fe812EbcB3cd8", + "timestamp": "1/16/2023, 8:51:51 AM" + }, + { + "address": "0x84Dc9a43B3472415a406e1a14d6b94a5c289eF7F", + "timestamp": "1/16/2023, 8:49:22 AM" + } + ] +} diff --git a/deployments/mumbai/solcInputs/0c2e3cb4979e1bddbff96ad838dc1107.json b/deployments/mumbai/solcInputs/0c2e3cb4979e1bddbff96ad838dc1107.json new file mode 100644 index 0000000..f82f910 --- /dev/null +++ b/deployments/mumbai/solcInputs/0c2e3cb4979e1bddbff96ad838dc1107.json @@ -0,0 +1,79 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Internal function that returns the initialized version. Returns `_initialized`\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Internal function that returns the initialized version. Returns `_initializing`\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721Upgradeable.sol\";\nimport \"./IERC721ReceiverUpgradeable.sol\";\nimport \"./extensions/IERC721MetadataUpgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../utils/StringsUpgradeable.sol\";\nimport \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {\n using AddressUpgradeable for address;\n using StringsUpgradeable for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC721_init_unchained(name_, symbol_);\n }\n\n function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n return\n interfaceId == type(IERC721Upgradeable).interfaceId ||\n interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721Upgradeable.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721Upgradeable.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721Upgradeable.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256, /* firstTokenId */\n uint256 batchSize\n ) internal virtual {\n if (batchSize > 1) {\n if (from != address(0)) {\n _balances[from] -= batchSize;\n }\n if (to != address(0)) {\n _balances[to] += batchSize;\n }\n }\n }\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[44] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721Upgradeable.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721MetadataUpgradeable is IERC721Upgradeable {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721ReceiverUpgradeable {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Base64.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n *\n * _Available since v4.5._\n */\nlibrary Base64 {\n /**\n * @dev Base64 Encoding/Decoding Table\n */\n string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /**\n * @dev Converts a `bytes` to its Bytes64 `string` representation.\n */\n function encode(bytes memory data) internal pure returns (string memory) {\n /**\n * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n */\n if (data.length == 0) return \"\";\n\n // Loads the table into memory\n string memory table = _TABLE;\n\n // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\n // and split into 4 numbers of 6 bits.\n // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\n // - `data.length + 2` -> Round up\n // - `/ 3` -> Number of 3-bytes chunks\n // - `4 *` -> 4 characters for each chunk\n string memory result = new string(4 * ((data.length + 2) / 3));\n\n /// @solidity memory-safe-assembly\n assembly {\n // Prepare the lookup table (skip the first \"length\" byte)\n let tablePtr := add(table, 1)\n\n // Prepare result pointer, jump over length\n let resultPtr := add(result, 32)\n\n // Run over the input, 3 bytes at a time\n for {\n let dataPtr := data\n let endPtr := add(data, mload(data))\n } lt(dataPtr, endPtr) {\n\n } {\n // Advance 3 bytes\n dataPtr := add(dataPtr, 3)\n let input := mload(dataPtr)\n\n // To write each character, shift the 3 bytes (18 bits) chunk\n // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n // and apply logical AND with 0x3F which is the number of\n // the previous character in the ASCII table prior to the Base64 Table\n // The result is then added to the table to get the character to write,\n // and finally write it in the result pointer but with a left shift\n // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n }\n\n // When data `bytes` is not exactly 3 bytes long\n // it is padded with `=` characters at the end\n switch mod(mload(data), 3)\n case 1 {\n mstore8(sub(resultPtr, 1), 0x3d)\n mstore8(sub(resultPtr, 2), 0x3d)\n }\n case 2 {\n mstore8(sub(resultPtr, 1), 0x3d)\n }\n }\n\n return result;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/FleekAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\ncontract FleekAccessControl is Initializable {\n using Counters for Counters.Counter;\n\n enum Roles {\n Owner,\n Controller\n }\n\n event TokenRoleGranted(uint256 indexed tokenId, Roles indexed role, address indexed toAddress, address byAddress);\n event TokenRoleRevoked(uint256 indexed tokenId, Roles indexed role, address indexed toAddress, address byAddress);\n event CollectionRoleGranted(Roles indexed role, address indexed toAddress, address byAddress);\n event CollectionRoleRevoked(Roles indexed role, address indexed toAddress, address byAddress);\n\n struct Role {\n mapping(address => uint256) indexes;\n address[] members;\n }\n\n Counters.Counter private _collectionRolesVersion;\n // _collectionRoles[version][role]\n mapping(uint256 => mapping(Roles => Role)) private _collectionRoles;\n\n mapping(uint256 => Counters.Counter) private _tokenRolesVersion;\n // _tokenRoles[tokenId][version][role]\n mapping(uint256 => mapping(uint256 => mapping(Roles => Role))) private _tokenRoles;\n\n /**\n * @dev Initializes the contract by granting the `Owner` role to the deployer.\n */\n function __FleekAccessControl_init() internal onlyInitializing {\n _grantCollectionRole(Roles.Owner, msg.sender);\n }\n\n /**\n * @dev Checks if the `msg.sender` has a certain role.\n */\n modifier requireCollectionRole(Roles role) {\n require(\n hasCollectionRole(role, msg.sender) || hasCollectionRole(Roles.Owner, msg.sender),\n \"FleekAccessControl: must have collection role\"\n );\n _;\n }\n\n /**\n * @dev Checks if the `msg.sender` has the `Token` role for a certain `tokenId`.\n */\n modifier requireTokenRole(uint256 tokenId, Roles role) {\n require(\n hasTokenRole(tokenId, role, msg.sender) || hasTokenRole(tokenId, Roles.Owner, msg.sender),\n \"FleekAccessControl: must have token role\"\n );\n _;\n }\n\n /**\n * @dev Grants the collection role to an address.\n *\n * Requirements:\n *\n * - the caller should have the collection role.\n *\n */\n function grantCollectionRole(Roles role, address account) public requireCollectionRole(Roles.Owner) {\n _grantCollectionRole(role, account);\n }\n\n /**\n * @dev Grants the token role to an address.\n *\n * Requirements:\n *\n * - the caller should have the token role.\n *\n */\n function grantTokenRole(\n uint256 tokenId,\n Roles role,\n address account\n ) public requireTokenRole(tokenId, Roles.Owner) {\n _grantTokenRole(tokenId, role, account);\n }\n\n /**\n * @dev Revokes the collection role of an address.\n *\n * Requirements:\n *\n * - the caller should have the collection role.\n *\n */\n function revokeCollectionRole(Roles role, address account) public requireCollectionRole(Roles.Owner) {\n _revokeCollectionRole(role, account);\n }\n\n /**\n * @dev Revokes the token role of an address.\n *\n * Requirements:\n *\n * - the caller should have the token role.\n *\n */\n function revokeTokenRole(\n uint256 tokenId,\n Roles role,\n address account\n ) public requireTokenRole(tokenId, Roles.Owner) {\n _revokeTokenRole(tokenId, role, account);\n }\n\n /**\n * @dev Returns `True` if a certain address has the collection role.\n */\n function hasCollectionRole(Roles role, address account) public view returns (bool) {\n uint256 currentVersion = _collectionRolesVersion.current();\n\n return _collectionRoles[currentVersion][role].indexes[account] != 0;\n }\n\n /**\n * @dev Returns `True` if a certain address has the token role.\n */\n function hasTokenRole(uint256 tokenId, Roles role, address account) public view returns (bool) {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n return _tokenRoles[tokenId][currentVersion][role].indexes[account] != 0;\n }\n\n /**\n * @dev Returns an array of addresses that all have the collection role.\n */\n function getCollectionRoleMembers(Roles role) public view returns (address[] memory) {\n uint256 currentVersion = _collectionRolesVersion.current();\n return _collectionRoles[currentVersion][role].members;\n }\n\n /**\n * @dev Returns an array of addresses that all have the same token role for a certain tokenId.\n */\n function getTokenRoleMembers(uint256 tokenId, Roles role) public view returns (address[] memory) {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n return _tokenRoles[tokenId][currentVersion][role].members;\n }\n\n /**\n * @dev Grants the collection role to an address.\n */\n function _grantCollectionRole(Roles role, address account) internal {\n uint256 currentVersion = _collectionRolesVersion.current();\n _grantRole(_collectionRoles[currentVersion][role], account);\n emit CollectionRoleGranted(role, account, msg.sender);\n }\n\n /**\n * @dev Revokes the collection role of an address.\n */\n function _revokeCollectionRole(Roles role, address account) internal {\n uint256 currentVersion = _collectionRolesVersion.current();\n _revokeRole(_collectionRoles[currentVersion][role], account);\n emit CollectionRoleRevoked(role, account, msg.sender);\n }\n\n /**\n * @dev Grants the token role to an address.\n */\n function _grantTokenRole(uint256 tokenId, Roles role, address account) internal {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n _grantRole(_tokenRoles[tokenId][currentVersion][role], account);\n emit TokenRoleGranted(tokenId, role, account, msg.sender);\n }\n\n /**\n * @dev Revokes the token role of an address.\n */\n function _revokeTokenRole(uint256 tokenId, Roles role, address account) internal {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n _revokeRole(_tokenRoles[tokenId][currentVersion][role], account);\n emit TokenRoleRevoked(tokenId, role, account, msg.sender);\n }\n\n /**\n * @dev Grants a certain role to a certain address.\n */\n function _grantRole(Role storage role, address account) internal {\n if (role.indexes[account] == 0) {\n role.members.push(account);\n role.indexes[account] = role.members.length;\n }\n }\n\n /**\n * @dev Revokes a certain role from a certain address.\n */\n function _revokeRole(Role storage role, address account) internal {\n if (role.indexes[account] != 0) {\n uint256 index = role.indexes[account] - 1;\n uint256 lastIndex = role.members.length - 1;\n address lastAccount = role.members[lastIndex];\n\n role.members[index] = lastAccount;\n role.indexes[lastAccount] = index + 1;\n\n role.members.pop();\n delete role.indexes[account];\n }\n }\n\n /**\n * @dev Clears all token roles for a certain tokenId.\n * Should only be used for burning tokens.\n */\n function _clearAllTokenRoles(uint256 tokenId) internal {\n _tokenRolesVersion[tokenId].increment();\n }\n\n /**\n * @dev Clears all token roles for a certain tokenId and grants the owner role to a new address.\n * Should only be used for transferring tokens.\n */\n function _clearAllTokenRoles(uint256 tokenId, address newOwner) internal {\n _clearAllTokenRoles(tokenId);\n _grantTokenRole(tokenId, Roles.Owner, newOwner);\n }\n}\n" + }, + "contracts/FleekERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts/utils/Base64.sol\";\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\nimport \"./FleekAccessControl.sol\";\n\ncontract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl {\n using Strings for uint256;\n using Counters for Counters.Counter;\n\n event NewBuild(uint256 indexed token, string indexed commitHash, address indexed triggeredBy);\n event NewTokenName(uint256 indexed token, string indexed name, address indexed triggeredBy);\n event NewTokenDescription(uint256 indexed token, string indexed description, address indexed triggeredBy);\n event NewTokenImage(uint256 indexed token, string indexed image, address indexed triggeredBy);\n event NewTokenExternalURL(uint256 indexed token, string indexed externalURL, address indexed triggeredBy);\n event NewTokenENS(uint256 indexed token, string indexed ENS, address indexed triggeredBy);\n\n /**\n * The properties are stored as string to keep consistency with\n * other token contracts, we might consider changing for bytes32\n * in the future due to gas optimization.\n */\n struct App {\n string name; // Name of the site\n string description; // Description about the site\n string externalURL; // Site URL\n string ENS; // ENS ID\n uint256 currentBuild; // The current build number (Increments by one with each change, starts at zero)\n mapping(uint256 => Build) builds; // Mapping to build details for each build number\n }\n\n /**\n * The metadata that is stored for each build.\n */\n struct Build {\n string commitHash;\n string gitRepository;\n }\n\n Counters.Counter private _tokenIds;\n mapping(uint256 => App) private _apps;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n function initialize(string memory _name, string memory _symbol) public initializer {\n __ERC721_init(_name, _symbol);\n __FleekAccessControl_init();\n }\n\n /**\n * @dev Checks if msg.sender has the role of tokenOwner for a certain tokenId.\n */\n modifier requireTokenOwner(uint256 tokenId) {\n require(msg.sender == ownerOf(tokenId), \"FleekERC721: must be token owner\");\n _;\n }\n\n /**\n * @dev Generates a SVG image.\n */\n function _generateSVG(string memory name, string memory ENS) internal view returns (string memory) {\n return (\n string(\n abi.encodePacked(\n _baseURI(),\n Base64.encode(\n abi.encodePacked(\n '',\n \"\",\n \"\",\n '',\n '',\n \"\",\n '',\n 'Fleek NFAs',\n \"\",\n '',\n '',\n name,\n '',\n ENS,\n \"\",\n \"\",\n \"\"\n )\n )\n )\n )\n );\n }\n\n /**\n * @dev Mints a token and returns a tokenId.\n *\n * If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event.\n *\n * Requirements:\n *\n * - the caller must have ``collectionOwner``'s admin role.\n *\n */\n function mint(\n address to,\n string memory name,\n string memory description,\n string memory externalURL,\n string memory ENS,\n string memory commitHash,\n string memory gitRepository\n ) public payable requireCollectionRole(Roles.Owner) returns (uint256) {\n uint256 tokenId = _tokenIds.current();\n _mint(to, tokenId);\n _tokenIds.increment();\n\n App storage app = _apps[tokenId];\n app.name = name;\n app.description = description;\n app.externalURL = externalURL;\n app.ENS = ENS;\n\n // The mint interaction is considered to be the first build of the site. Updates from now on all increment the currentBuild by one and update the mapping.\n app.currentBuild = 0;\n app.builds[0] = Build(commitHash, gitRepository);\n\n return tokenId;\n }\n\n /**\n * @dev Returns the token metadata associated with the `tokenId`.\n *\n * Returns a based64 encoded string value of the URI.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n *\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n address owner = ownerOf(tokenId);\n App storage app = _apps[tokenId];\n\n // prettier-ignore\n bytes memory dataURI = abi.encodePacked(\n '{',\n '\"name\":\"', app.name, '\",',\n '\"description\":\"', app.description, '\",',\n '\"owner\":\"', Strings.toHexString(uint160(owner), 20), '\",',\n '\"external_url\":\"', app.externalURL, '\",',\n '\"image\":\"', _generateSVG(app.name, app.ENS), '\",',\n '\"attributes\": [',\n '{\"trait_type\": \"ENS\", \"value\":\"', app.ENS,'\"},',\n '{\"trait_type\": \"Commit Hash\", \"value\":\"', app.builds[app.currentBuild].commitHash,'\"},',\n '{\"trait_type\": \"Repository\", \"value\":\"', app.builds[app.currentBuild].gitRepository,'\"},',\n '{\"trait_type\": \"Version\", \"value\":\"', Strings.toString(app.currentBuild),'\"}',\n ']',\n '}'\n );\n\n return string(abi.encodePacked(_baseURI(), Base64.encode((dataURI))));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Upgradeable) returns (bool) {\n return super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Override of _beforeTokenTransfer of ERC721.\n * Here it needs to update the token controller roles for mint, burn and transfer.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId,\n uint256 batchSize\n ) internal virtual override {\n if (from != address(0) && to != address(0)) {\n // Transfer\n _clearAllTokenRoles(tokenId, to);\n } else if (from == address(0)) {\n // Mint\n _grantTokenRole(tokenId, Roles.Owner, to);\n } else if (to == address(0)) {\n // Burn\n _clearAllTokenRoles(tokenId);\n }\n super._beforeTokenTransfer(from, to, tokenId, batchSize);\n }\n\n /**\n * @dev A baseURI internal function implementation to be called in the `tokenURI` function.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return \"data:application/json;base64,\";\n }\n\n /**\n * @dev Updates the `externalURL` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenExternalURL} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenExternalURL(\n uint256 tokenId,\n string memory _tokenExternalURL\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].externalURL = _tokenExternalURL;\n emit NewTokenExternalURL(tokenId, _tokenExternalURL, msg.sender);\n }\n\n /**\n * @dev Updates the `ENS` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenENS} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenENS(\n uint256 tokenId,\n string memory _tokenENS\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].ENS = _tokenENS;\n emit NewTokenENS(tokenId, _tokenENS, msg.sender);\n }\n\n /**\n * @dev Updates the `name` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenName} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenName(\n uint256 tokenId,\n string memory _tokenName\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].name = _tokenName;\n emit NewTokenName(tokenId, _tokenName, msg.sender);\n }\n\n /**\n * @dev Updates the `description` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenDescription} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenDescription(\n uint256 tokenId,\n string memory _tokenDescription\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].description = _tokenDescription;\n emit NewTokenDescription(tokenId, _tokenDescription, msg.sender);\n }\n\n /**\n * @dev Adds a new build to a minted `tokenId`'s builds mapping.\n *\n * May emit a {NewBuild} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenBuild(\n uint256 tokenId,\n string memory _commitHash,\n string memory _gitRepository\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].builds[++_apps[tokenId].currentBuild] = Build(_commitHash, _gitRepository);\n emit NewBuild(tokenId, _commitHash, msg.sender);\n }\n\n /**\n * @dev Burns a previously minted `tokenId`.\n *\n * May emit a {Transfer} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenOwner` role.\n *\n */\n function burn(uint256 tokenId) public virtual requireTokenRole(tokenId, Roles.Owner) {\n super._burn(tokenId);\n\n if (bytes(_apps[tokenId].externalURL).length != 0) {\n delete _apps[tokenId];\n }\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": false + } + }, + "viaIR": false, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "storageLayout" + ], + "": ["ast"] + } + } + } +} diff --git a/deployments/mumbai/solcInputs/0ee8c4d44ebad02e2364970b68450c98.json b/deployments/mumbai/solcInputs/0ee8c4d44ebad02e2364970b68450c98.json deleted file mode 100644 index 711ec5a..0000000 --- a/deployments/mumbai/solcInputs/0ee8c4d44ebad02e2364970b68450c98.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts/access/AccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" - }, - "@openzeppelin/contracts/access/IAccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256, /* firstTokenId */\n uint256 batchSize\n ) internal virtual {\n if (batchSize > 1) {\n if (from != address(0)) {\n _balances[from] -= batchSize;\n }\n if (to != address(0)) {\n _balances[to] += batchSize;\n }\n }\n }\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Base64.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n *\n * _Available since v4.5._\n */\nlibrary Base64 {\n /**\n * @dev Base64 Encoding/Decoding Table\n */\n string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /**\n * @dev Converts a `bytes` to its Bytes64 `string` representation.\n */\n function encode(bytes memory data) internal pure returns (string memory) {\n /**\n * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n */\n if (data.length == 0) return \"\";\n\n // Loads the table into memory\n string memory table = _TABLE;\n\n // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\n // and split into 4 numbers of 6 bits.\n // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\n // - `data.length + 2` -> Round up\n // - `/ 3` -> Number of 3-bytes chunks\n // - `4 *` -> 4 characters for each chunk\n string memory result = new string(4 * ((data.length + 2) / 3));\n\n /// @solidity memory-safe-assembly\n assembly {\n // Prepare the lookup table (skip the first \"length\" byte)\n let tablePtr := add(table, 1)\n\n // Prepare result pointer, jump over length\n let resultPtr := add(result, 32)\n\n // Run over the input, 3 bytes at a time\n for {\n let dataPtr := data\n let endPtr := add(data, mload(data))\n } lt(dataPtr, endPtr) {\n\n } {\n // Advance 3 bytes\n dataPtr := add(dataPtr, 3)\n let input := mload(dataPtr)\n\n // To write each character, shift the 3 bytes (18 bits) chunk\n // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n // and apply logical AND with 0x3F which is the number of\n // the previous character in the ASCII table prior to the Base64 Table\n // The result is then added to the table to get the character to write,\n // and finally write it in the result pointer but with a left shift\n // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n }\n\n // When data `bytes` is not exactly 3 bytes long\n // it is padded with `=` characters at the end\n switch mod(mload(data), 3)\n case 1 {\n mstore8(sub(resultPtr, 1), 0x3d)\n mstore8(sub(resultPtr, 2), 0x3d)\n }\n case 2 {\n mstore8(sub(resultPtr, 1), 0x3d)\n }\n }\n\n return result;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Counters.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "contracts/FleekAccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\r\n\r\npragma solidity ^0.8.7;\r\n\r\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\r\n\r\nabstract contract FleekAccessControl is AccessControl {\r\n bytes32 public constant COLLECTION_OWNER_ROLE =\r\n keccak256(\"COLLECTION_OWNER_ROLE\");\r\n bytes32 public constant COLLECTION_CONTROLLER_ROLE =\r\n keccak256(\"COLLECTION_CONTROLLER_ROLE\");\r\n\r\n constructor() {\r\n _setRoleAdmin(COLLECTION_OWNER_ROLE, DEFAULT_ADMIN_ROLE);\r\n _grantRole(COLLECTION_OWNER_ROLE, msg.sender);\r\n }\r\n\r\n modifier requireCollectionOwner() {\r\n require(\r\n hasRole(COLLECTION_OWNER_ROLE, msg.sender),\r\n \"FleekAccessControl: must have collection owner role\"\r\n );\r\n _;\r\n }\r\n\r\n modifier requireCollectionController() {\r\n require(\r\n hasRole(COLLECTION_OWNER_ROLE, msg.sender) ||\r\n hasRole(COLLECTION_CONTROLLER_ROLE, msg.sender),\r\n \"FleekAccessControl: must have collection controller role\"\r\n );\r\n _;\r\n }\r\n\r\n modifier requireTokenController(uint256 tokenId) {\r\n require(\r\n hasRole(_tokenRole(tokenId, \"CONTROLLER\"), msg.sender),\r\n \"FleekAccessControl: must have token role\"\r\n );\r\n _;\r\n }\r\n\r\n function isTokenController(\r\n uint256 tokenId,\r\n address account\r\n ) public view returns (bool) {\r\n return hasRole(_tokenRole(tokenId, \"CONTROLLER\"), account);\r\n }\r\n\r\n function _tokenRole(\r\n uint256 tokenId,\r\n string memory role\r\n ) internal pure returns (bytes32) {\r\n return keccak256(abi.encodePacked(\"TOKEN_\", role, tokenId));\r\n }\r\n\r\n function _clearTokenControllers(uint256 tokenId) internal {\r\n // TODO: Remove token controllers from AccessControl\r\n }\r\n}\r\n" - }, - "contracts/FleekERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts/utils/Base64.sol\";\nimport \"./FleekAccessControl.sol\";\n\ncontract FleekERC721 is ERC721, FleekAccessControl {\n using Strings for uint256;\n using Counters for Counters.Counter;\n\n event NewBuild(uint256 indexed token, string indexed commit_hash);\n event NewTokenName(uint256 indexed token, string indexed name);\n event NewTokenDescription(uint256 indexed token, string indexed description);\n event NewTokenImage(uint256 indexed token, string indexed image);\n event NewTokenExternalURL(uint256 indexed token, string indexed external_url);\n event NewTokenENS(uint256 indexed token, string indexed ENS);\n\n struct Build {\n string commit_hash;\n string git_repository;\n string author;\n }\n\n /**\n * The properties are stored as string to keep consistency with\n * other token contracts, we might consider changing for bytes32\n * in the future due to gas optimization\n */\n struct App {\n string name; // Name of the site\n string description; // Description about the site\n string image; // Preview Image IPFS Link\n string external_url; // Site URL\n string ENS; // ENS ID\n uint256 current_build; // The current build number (Increments by one with each change, starts at zero)\n mapping(uint256 => Build) builds; // Mapping to build details for each build number\n }\n\n Counters.Counter private _tokenIds;\n mapping(uint256 => App) private _apps;\n\n constructor(\n string memory _name,\n string memory _symbol\n ) ERC721(_name, _symbol) {}\n\n modifier requireTokenOwner(uint256 tokenId) {\n require(\n msg.sender == ownerOf(tokenId),\n \"FleekERC721: must be token owner\"\n );\n _;\n }\n\n function mint(\n address to,\n string memory name,\n string memory description,\n string memory image,\n string memory external_url,\n string memory ENS,\n string memory commit_hash,\n string memory git_repository,\n string memory author\n ) public payable requireCollectionOwner returns (uint256) {\n uint256 tokenId = _tokenIds.current();\n _mint(to, tokenId);\n _tokenIds.increment();\n\n App storage app = _apps[tokenId];\n app.name = name;\n app.description = description;\n app.image = image;\n app.external_url = external_url;\n app.ENS = ENS;\n\n // The mint interaction is considered to be the first build of the site. Updates from now on all increment the current_build by one and update the mapping.\n app.current_build = 0;\n app.builds[0] = Build(commit_hash, git_repository, author);\n\n return tokenId;\n }\n\n function tokenURI(\n uint256 tokenId\n ) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n address owner = ownerOf(tokenId);\n App storage app = _apps[tokenId];\n\n bytes memory dataURI = abi.encodePacked(\n '{',\n '\"name\":\"', app.name, '\",',\n '\"description\":\"', app.description, '\",',\n '\"owner\":\"', Strings.toHexString(uint160(owner), 20), '\",',\n '\"external_url\":\"', app.external_url, '\",',\n '\"image\":\"', app.image, '\",',\n '\"attributes\": [',\n '{\"trait_type\": \"ENS\", \"value\":\"', app.ENS,'\"},',\n '{\"trait_type\": \"Commit Hash\", \"value\":\"', app.builds[app.current_build].commit_hash,'\"},',\n '{\"trait_type\": \"Repository\", \"value\":\"', app.builds[app.current_build].git_repository,'\"},',\n '{\"trait_type\": \"Author\", \"value\":\"', app.builds[app.current_build].author,'\"},',\n '{\"trait_type\": \"Version\", \"value\":\"', Strings.toString(app.current_build),'\"}',\n ']',\n '}'\n );\n\n return string(abi.encodePacked(_baseURI(), Base64.encode((dataURI))));\n }\n\n function addTokenController(\n uint256 tokenId,\n address controller\n ) public requireTokenOwner(tokenId) {\n _requireMinted(tokenId);\n _grantRole(_tokenRole(tokenId, \"CONTROLLER\"), controller);\n }\n\n function removeTokenController(\n uint256 tokenId,\n address controller\n ) public requireTokenOwner(tokenId) {\n _requireMinted(tokenId);\n _revokeRole(_tokenRole(tokenId, \"CONTROLLER\"), controller);\n }\n\n function supportsInterface(\n bytes4 interfaceId\n ) public view virtual override(ERC721, AccessControl) returns (bool) {\n return super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Override of _beforeTokenTransfer of ERC721.\n * Here it needs to update the token controller roles for mint, burn and transfer.\n * IMPORTANT: The function for clearing token controllers is not implemented yet.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId,\n uint256 batchSize\n ) internal virtual override {\n if (from != address(0) && to != address(0)) {\n // Transfer\n _clearTokenControllers(tokenId);\n _grantRole(_tokenRole(tokenId, \"CONTROLLER\"), to);\n } else if (from == address(0)) {\n // Mint\n _grantRole(_tokenRole(tokenId, \"CONTROLLER\"), to);\n } else if (to == address(0)) {\n // Burn\n _clearTokenControllers(tokenId);\n }\n super._beforeTokenTransfer(from, to, tokenId, batchSize);\n }\n\n function _baseURI() internal view virtual override returns (string memory) {\n return \"data:application/json;base64,\";\n }\n\n function setTokenExternalURL(\n uint256 tokenId,\n string memory _tokenExternalURL\n ) public virtual requireTokenController(tokenId) {\n _requireMinted(tokenId);\n _apps[tokenId].external_url = _tokenExternalURL;\n emit NewTokenExternalURL(tokenId, _tokenExternalURL);\n }\n\n function setTokenENS(\n uint256 tokenId,\n string memory _tokenENS\n ) public virtual requireTokenController(tokenId) {\n _requireMinted(tokenId);\n _apps[tokenId].ENS = _tokenENS;\n emit NewTokenENS(tokenId, _tokenENS);\n }\n\n function setTokenName(\n uint256 tokenId,\n string memory _tokenName\n ) public virtual requireTokenController(tokenId) {\n _requireMinted(tokenId);\n _apps[tokenId].name = _tokenName;\n emit NewTokenName(tokenId, _tokenName);\n }\n\n function setTokenDescription(\n uint256 tokenId,\n string memory _tokenDescription\n ) public virtual requireTokenController(tokenId) {\n _requireMinted(tokenId);\n _apps[tokenId].description = _tokenDescription;\n emit NewTokenDescription(tokenId, _tokenDescription);\n }\n\n function setTokenImage(\n uint256 tokenId,\n string memory _tokenImage\n ) public virtual requireTokenController(tokenId) {\n _requireMinted(tokenId);\n _apps[tokenId].image = _tokenImage;\n emit NewTokenImage(tokenId, _tokenImage);\n }\n\n function setTokenBuild(\n uint256 tokenId,\n string memory _commit_hash,\n string memory _git_repository,\n string memory _author\n ) public virtual requireTokenController(tokenId) {\n _requireMinted(tokenId);\n _apps[tokenId].builds[++_apps[tokenId].current_build] = Build(\n _commit_hash,\n _git_repository,\n _author\n );\n emit NewBuild(tokenId, _commit_hash);\n }\n\n function burn(\n uint256 tokenId\n ) public virtual requireTokenOwner(tokenId) {\n super._burn(tokenId);\n\n if (bytes(_apps[tokenId].external_url).length != 0) {\n delete _apps[tokenId];\n }\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": ["ast"] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} diff --git a/deployments/mumbai/solcInputs/b88731ab6401d18abef5bd8425a23961.json b/deployments/mumbai/solcInputs/b88731ab6401d18abef5bd8425a23961.json deleted file mode 100644 index 75e2318..0000000 --- a/deployments/mumbai/solcInputs/b88731ab6401d18abef5bd8425a23961.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts/token/ERC721/ERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _ownerOf(tokenId);\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner or approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: caller is not token owner or approved\");\n _safeTransfer(from, to, tokenId, data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n return _owners[tokenId];\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _ownerOf(tokenId) != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId, 1);\n\n // Check that tokenId was not minted by `_beforeTokenTransfer` hook\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n unchecked {\n // Will not overflow unless all 2**256 token ids are minted to the same owner.\n // Given that tokens are minted one by one, it is impossible in practice that\n // this ever happens. Might change if we allow batch minting.\n // The ERC fails to describe this case.\n _balances[to] += 1;\n }\n\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId, 1);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId, 1);\n\n // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook\n owner = ERC721.ownerOf(tokenId);\n\n // Clear approvals\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // Cannot overflow, as that would require more tokens to be burned/transferred\n // out than the owner initially received through minting and transferring in.\n _balances[owner] -= 1;\n }\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId, 1);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId, 1);\n\n // Check that tokenId was not transferred by `_beforeTokenTransfer` hook\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n\n // Clear approvals from the previous owner\n delete _tokenApprovals[tokenId];\n\n unchecked {\n // `_balances[from]` cannot overflow for the same reason as described in `_burn`:\n // `from`'s balance is the number of token held, which is at least one before the current\n // transfer.\n // `_balances[to]` could overflow in the conditions described in `_mint`. That would require\n // all 2**256 token ids to be minted, which in practice is impossible.\n _balances[from] -= 1;\n _balances[to] += 1;\n }\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId, 1);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits an {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Reverts if the `tokenId` has not been minted yet.\n */\n function _requireMinted(uint256 tokenId) internal view virtual {\n require(_exists(tokenId), \"ERC721: invalid token ID\");\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n /// @solidity memory-safe-assembly\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.\n * - When `from` is zero, the tokens will be minted for `to`.\n * - When `to` is zero, ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256, /* firstTokenId */\n uint256 batchSize\n ) internal virtual {\n if (batchSize > 1) {\n if (from != address(0)) {\n _balances[from] -= batchSize;\n }\n if (to != address(0)) {\n _balances[to] += batchSize;\n }\n }\n }\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is\n * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.\n * - When `from` is zero, the tokens were minted for `to`.\n * - When `to` is zero, ``from``'s tokens were burned.\n * - `from` and `to` are never both zero.\n * - `batchSize` is non-zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 firstTokenId,\n uint256 batchSize\n ) internal virtual {}\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n * understand this adds an external call which potentially creates a reentrancy vulnerability.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Base64.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n *\n * _Available since v4.5._\n */\nlibrary Base64 {\n /**\n * @dev Base64 Encoding/Decoding Table\n */\n string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n /**\n * @dev Converts a `bytes` to its Bytes64 `string` representation.\n */\n function encode(bytes memory data) internal pure returns (string memory) {\n /**\n * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n */\n if (data.length == 0) return \"\";\n\n // Loads the table into memory\n string memory table = _TABLE;\n\n // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\n // and split into 4 numbers of 6 bits.\n // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\n // - `data.length + 2` -> Round up\n // - `/ 3` -> Number of 3-bytes chunks\n // - `4 *` -> 4 characters for each chunk\n string memory result = new string(4 * ((data.length + 2) / 3));\n\n /// @solidity memory-safe-assembly\n assembly {\n // Prepare the lookup table (skip the first \"length\" byte)\n let tablePtr := add(table, 1)\n\n // Prepare result pointer, jump over length\n let resultPtr := add(result, 32)\n\n // Run over the input, 3 bytes at a time\n for {\n let dataPtr := data\n let endPtr := add(data, mload(data))\n } lt(dataPtr, endPtr) {\n\n } {\n // Advance 3 bytes\n dataPtr := add(dataPtr, 3)\n let input := mload(dataPtr)\n\n // To write each character, shift the 3 bytes (18 bits) chunk\n // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n // and apply logical AND with 0x3F which is the number of\n // the previous character in the ASCII table prior to the Base64 Table\n // The result is then added to the table to get the character to write,\n // and finally write it in the result pointer but with a left shift\n // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n\n mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n resultPtr := add(resultPtr, 1) // Advance\n }\n\n // When data `bytes` is not exactly 3 bytes long\n // it is padded with `=` characters at the end\n switch mod(mload(data), 3)\n case 1 {\n mstore8(sub(resultPtr, 1), 0x3d)\n mstore8(sub(resultPtr, 2), 0x3d)\n }\n case 2 {\n mstore8(sub(resultPtr, 1), 0x3d)\n }\n }\n\n return result;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Counters.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/ERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" - }, - "@openzeppelin/contracts/utils/introspection/IERC165.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" - }, - "@openzeppelin/contracts/utils/math/Math.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "contracts/FleekAccessControl.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\n\ncontract FleekAccessControl {\n using Counters for Counters.Counter;\n\n enum Roles {\n Owner,\n Controller\n }\n\n event TokenRoleGranted(uint256 indexed tokenId, Roles indexed role, address indexed toAddress, address byAddress);\n event TokenRoleRevoked(uint256 indexed tokenId, Roles indexed role, address indexed toAddress, address byAddress);\n event CollectionRoleGranted(Roles indexed role, address indexed toAddress, address byAddress);\n event CollectionRoleRevoked(Roles indexed role, address indexed toAddress, address byAddress);\n\n struct Role {\n mapping(address => uint256) indexes;\n address[] members;\n }\n\n Counters.Counter private _collectionRolesVersion;\n // _collectionRoles[version][role]\n mapping(uint256 => mapping(Roles => Role)) private _collectionRoles;\n\n mapping(uint256 => Counters.Counter) private _tokenRolesVersion;\n // _tokenRoles[tokenId][version][role]\n mapping(uint256 => mapping(uint256 => mapping(Roles => Role))) private _tokenRoles;\n\n constructor() {\n _grantCollectionRole(Roles.Owner, msg.sender);\n }\n\n modifier requireCollectionRole(Roles role) {\n require(\n hasCollectionRole(role, msg.sender) || hasCollectionRole(Roles.Owner, msg.sender),\n \"FleekAccessControl: must have collection role\"\n );\n _;\n }\n\n modifier requireTokenRole(uint256 tokenId, Roles role) {\n require(\n hasTokenRole(tokenId, role, msg.sender) || hasTokenRole(tokenId, Roles.Owner, msg.sender),\n \"FleekAccessControl: must have token role\"\n );\n _;\n }\n\n /**\n * @dev Grants the collection role to an address.\n *\n * Requirements:\n *\n * - the caller should have the collection role.\n *\n */\n function grantCollectionRole(Roles role, address account) public requireCollectionRole(Roles.Owner) {\n _grantCollectionRole(role, account);\n }\n\n /**\n * @dev Grants the token role to an address.\n *\n * Requirements:\n *\n * - the caller should have the token role.\n *\n */\n function grantTokenRole(\n uint256 tokenId,\n Roles role,\n address account\n ) public requireTokenRole(tokenId, Roles.Owner) {\n _grantTokenRole(tokenId, role, account);\n }\n\n /**\n * @dev Revokes the collection role of an address.\n *\n * Requirements:\n *\n * - the caller should have the collection role.\n *\n */\n function revokeCollectionRole(Roles role, address account) public requireCollectionRole(Roles.Owner) {\n _revokeCollectionRole(role, account);\n }\n\n /**\n * @dev Revokes the token role of an address.\n *\n * Requirements:\n *\n * - the caller should have the token role.\n *\n */\n function revokeTokenRole(\n uint256 tokenId,\n Roles role,\n address account\n ) public requireTokenRole(tokenId, Roles.Owner) {\n _revokeTokenRole(tokenId, role, account);\n }\n\n /**\n * @dev Returns `True` if a certain address has the collection role.\n */\n function hasCollectionRole(Roles role, address account) public view returns (bool) {\n uint256 currentVersion = _collectionRolesVersion.current();\n\n return _collectionRoles[currentVersion][role].indexes[account] != 0;\n }\n\n /**\n * @dev Returns `True` if a certain address has the token role.\n */\n function hasTokenRole(uint256 tokenId, Roles role, address account) public view returns (bool) {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n return _tokenRoles[tokenId][currentVersion][role].indexes[account] != 0;\n }\n\n /**\n * @dev Returns an array of addresses that all have the collection role.\n */\n function getCollectionRoleMembers(Roles role) public view returns (address[] memory) {\n uint256 currentVersion = _collectionRolesVersion.current();\n return _collectionRoles[currentVersion][role].members;\n }\n\n /**\n * @dev Returns an array of addresses that all have the same token role for a certain tokenId.\n */\n function getTokenRoleMembers(uint256 tokenId, Roles role) public view returns (address[] memory) {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n return _tokenRoles[tokenId][currentVersion][role].members;\n }\n\n /**\n * @dev Grants the collection role to an address.\n */\n function _grantCollectionRole(Roles role, address account) internal {\n uint256 currentVersion = _collectionRolesVersion.current();\n _grantRole(_collectionRoles[currentVersion][role], account);\n emit CollectionRoleGranted(role, account, msg.sender);\n }\n\n /**\n * @dev Revokes the collection role of an address.\n */\n function _revokeCollectionRole(Roles role, address account) internal {\n uint256 currentVersion = _collectionRolesVersion.current();\n _revokeRole(_collectionRoles[currentVersion][role], account);\n emit CollectionRoleRevoked(role, account, msg.sender);\n }\n\n /**\n * @dev Grants the token role to an address.\n */\n function _grantTokenRole(uint256 tokenId, Roles role, address account) internal {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n _grantRole(_tokenRoles[tokenId][currentVersion][role], account);\n emit TokenRoleGranted(tokenId, role, account, msg.sender);\n }\n\n /**\n * @dev Revokes the token role of an address.\n */\n function _revokeTokenRole(uint256 tokenId, Roles role, address account) internal {\n uint256 currentVersion = _tokenRolesVersion[tokenId].current();\n _revokeRole(_tokenRoles[tokenId][currentVersion][role], account);\n emit TokenRoleRevoked(tokenId, role, account, msg.sender);\n }\n\n /**\n * @dev Grants a certain role to a certain address.\n */\n function _grantRole(Role storage role, address account) internal {\n if (role.indexes[account] == 0) {\n role.members.push(account);\n role.indexes[account] = role.members.length;\n }\n }\n\n /**\n * @dev Revokes a certain role from a certain address.\n */\n function _revokeRole(Role storage role, address account) internal {\n if (role.indexes[account] != 0) {\n uint256 index = role.indexes[account] - 1;\n uint256 lastIndex = role.members.length - 1;\n address lastAccount = role.members[lastIndex];\n\n role.members[index] = lastAccount;\n role.indexes[lastAccount] = index + 1;\n\n role.members.pop();\n delete role.indexes[account];\n }\n }\n\n /**\n * @dev Clears all token roles for a certain tokenId.\n * Should only be used for burning tokens.\n */\n function _clearAllTokenRoles(uint256 tokenId) internal {\n _tokenRolesVersion[tokenId].increment();\n }\n\n /**\n * @dev Clears all token roles for a certain tokenId and grants the owner role to a new address.\n * Should only be used for transferring tokens.\n */\n function _clearAllTokenRoles(uint256 tokenId, address newOwner) internal {\n _clearAllTokenRoles(tokenId);\n _grantTokenRole(tokenId, Roles.Owner, newOwner);\n }\n}\n" - }, - "contracts/FleekERC721.sol": { - "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport \"@openzeppelin/contracts/utils/Counters.sol\";\nimport \"@openzeppelin/contracts/utils/Base64.sol\";\nimport \"./FleekAccessControl.sol\";\n\ncontract FleekERC721 is ERC721, FleekAccessControl {\n using Strings for uint256;\n using Counters for Counters.Counter;\n\n event NewBuild(uint256 indexed token, string indexed commitHash, address indexed triggeredBy);\n event NewTokenName(uint256 indexed token, string indexed name, address indexed triggeredBy);\n event NewTokenDescription(uint256 indexed token, string indexed description, address indexed triggeredBy);\n event NewTokenImage(uint256 indexed token, string indexed image, address indexed triggeredBy);\n event NewTokenExternalURL(uint256 indexed token, string indexed externalURL, address indexed triggeredBy);\n event NewTokenENS(uint256 indexed token, string indexed ENS, address indexed triggeredBy);\n\n struct Build {\n string commitHash;\n string gitRepository;\n }\n\n /**\n * The properties are stored as string to keep consistency with\n * other token contracts, we might consider changing for bytes32\n * in the future due to gas optimization\n */\n struct App {\n string name; // Name of the site\n string description; // Description about the site\n string image; // Preview Image IPFS Link\n string externalURL; // Site URL\n string ENS; // ENS ID\n uint256 currentBuild; // The current build number (Increments by one with each change, starts at zero)\n mapping(uint256 => Build) builds; // Mapping to build details for each build number\n }\n\n Counters.Counter private _tokenIds;\n mapping(uint256 => App) private _apps;\n\n constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}\n\n modifier requireTokenOwner(uint256 tokenId) {\n require(msg.sender == ownerOf(tokenId), \"FleekERC721: must be token owner\");\n _;\n }\n\n /**\n * @dev Mints a token and returns a tokenId.\n *\n * If the `tokenId` has not been minted before, and the `to` address is not zero, emits a {Transfer} event.\n *\n * Requirements:\n *\n * - the caller must have ``collectionOwner``'s admin role.\n *\n */\n function mint(\n address to,\n string memory name,\n string memory description,\n string memory image,\n string memory externalURL,\n string memory ENS,\n string memory commitHash,\n string memory gitRepository\n ) public payable requireCollectionRole(Roles.Owner) returns (uint256) {\n uint256 tokenId = _tokenIds.current();\n _mint(to, tokenId);\n _tokenIds.increment();\n\n App storage app = _apps[tokenId];\n app.name = name;\n app.description = description;\n app.image = image;\n app.externalURL = externalURL;\n app.ENS = ENS;\n\n // The mint interaction is considered to be the first build of the site. Updates from now on all increment the currentBuild by one and update the mapping.\n app.currentBuild = 0;\n app.builds[0] = Build(commitHash, gitRepository);\n\n return tokenId;\n }\n\n /**\n * @dev Returns the token metadata associated with the `tokenId`.\n *\n * Returns a based64 encoded string value of the URI.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n *\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n address owner = ownerOf(tokenId);\n App storage app = _apps[tokenId];\n\n // prettier-ignore\n bytes memory dataURI = abi.encodePacked(\n '{',\n '\"name\":\"', app.name, '\",',\n '\"description\":\"', app.description, '\",',\n '\"owner\":\"', Strings.toHexString(uint160(owner), 20), '\",',\n '\"external_url\":\"', app.externalURL, '\",',\n '\"image\":\"', app.image, '\",',\n '\"attributes\": [',\n '{\"trait_type\": \"ENS\", \"value\":\"', app.ENS,'\"},',\n '{\"trait_type\": \"Commit Hash\", \"value\":\"', app.builds[app.currentBuild].commitHash,'\"},',\n '{\"trait_type\": \"Repository\", \"value\":\"', app.builds[app.currentBuild].gitRepository,'\"},',\n '{\"trait_type\": \"Version\", \"value\":\"', Strings.toString(app.currentBuild),'\"}',\n ']',\n '}'\n );\n\n return string(abi.encodePacked(_baseURI(), Base64.encode((dataURI))));\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) {\n return super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Override of _beforeTokenTransfer of ERC721.\n * Here it needs to update the token controller roles for mint, burn and transfer.\n * IMPORTANT: The function for clearing token controllers is not implemented yet.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId,\n uint256 batchSize\n ) internal virtual override {\n if (from != address(0) && to != address(0)) {\n // Transfer\n _clearAllTokenRoles(tokenId, to);\n } else if (from == address(0)) {\n // Mint\n _grantTokenRole(tokenId, Roles.Owner, to);\n } else if (to == address(0)) {\n // Burn\n _clearAllTokenRoles(tokenId);\n }\n super._beforeTokenTransfer(from, to, tokenId, batchSize);\n }\n\n /**\n * @dev A baseURI internal function implementation to be called in the `tokenURI` function.\n */\n function _baseURI() internal view virtual override returns (string memory) {\n return \"data:application/json;base64,\";\n }\n\n /**\n * @dev Updates the `externalURL` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenExternalURL} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenExternalURL(\n uint256 tokenId,\n string memory _tokenExternalURL\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].externalURL = _tokenExternalURL;\n emit NewTokenExternalURL(tokenId, _tokenExternalURL, msg.sender);\n }\n\n /**\n * @dev Updates the `ENS` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenENS} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenENS(\n uint256 tokenId,\n string memory _tokenENS\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].ENS = _tokenENS;\n emit NewTokenENS(tokenId, _tokenENS, msg.sender);\n }\n\n /**\n * @dev Updates the `name` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenName} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenName(\n uint256 tokenId,\n string memory _tokenName\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].name = _tokenName;\n emit NewTokenName(tokenId, _tokenName, msg.sender);\n }\n\n /**\n * @dev Updates the `description` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenDescription} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenDescription(\n uint256 tokenId,\n string memory _tokenDescription\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].description = _tokenDescription;\n emit NewTokenDescription(tokenId, _tokenDescription, msg.sender);\n }\n\n /**\n * @dev Updates the `image` metadata field of a minted `tokenId`.\n *\n * May emit a {NewTokenImage} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenImage(\n uint256 tokenId,\n string memory _tokenImage\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].image = _tokenImage;\n emit NewTokenImage(tokenId, _tokenImage, msg.sender);\n }\n\n /**\n * @dev Adds a new build to a minted `tokenId`'s builds mapping.\n *\n * May emit a {NewBuild} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenController` role.\n *\n */\n function setTokenBuild(\n uint256 tokenId,\n string memory _commitHash,\n string memory _gitRepository\n ) public virtual requireTokenRole(tokenId, Roles.Controller) {\n _requireMinted(tokenId);\n _apps[tokenId].builds[++_apps[tokenId].currentBuild] = Build(_commitHash, _gitRepository);\n emit NewBuild(tokenId, _commitHash, msg.sender);\n }\n\n /**\n * @dev Burns a previously minted `tokenId`.\n *\n * May emit a {Transfer} event.\n *\n * Requirements:\n *\n * - the tokenId must be minted and valid.\n * - the sender must have the `tokenOwner` role.\n *\n */\n function burn(uint256 tokenId) public virtual requireTokenRole(tokenId, Roles.Owner) {\n super._burn(tokenId);\n\n if (bytes(_apps[tokenId].externalURL).length != 0) {\n delete _apps[tokenId];\n }\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": ["ast"] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} diff --git a/hardhat.config.ts b/hardhat.config.ts index 61aab3e..d75527a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -2,10 +2,10 @@ import '@nomiclabs/hardhat-etherscan'; import '@nomiclabs/hardhat-ethers'; import '@nomiclabs/hardhat-web3'; import '@nomicfoundation/hardhat-chai-matchers'; -import 'hardhat-deploy'; import 'solidity-coverage'; import 'hardhat-gas-reporter'; import 'hardhat-contract-sizer'; +import '@openzeppelin/hardhat-upgrades'; import * as dotenv from 'dotenv'; import { HardhatUserConfig } from 'hardhat/types'; @@ -24,13 +24,9 @@ const config: HardhatUserConfig = { hardhat: { chainId: 31337, }, - localhost: { - chainId: 31337, - }, mumbai: { url: API_URL, accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [], - saveDeployments: true, chainId: 80001, }, }, @@ -45,14 +41,6 @@ const config: HardhatUserConfig = { runOnCompile: false, only: ['NftMarketplace'], }, - namedAccounts: { - localDeployer: { - default: 0, - }, - privateKey: { - default: PRIVATE_KEY ? `privatekey://${PRIVATE_KEY}` : null, - }, - }, solidity: { version: '0.8.12', settings: { diff --git a/package.json b/package.json index a6f3388..8d03daf 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,9 @@ "test:foundry": "forge test --via-ir", "test:hardhat": "hardhat test", "format": "prettier --write \"./**/*.{js,json,sol,ts}\"", - "node:hardhat": "hardhat node --tags local", - "deploy:local": "hardhat deploy --tags local --network localhost", - "deploy:mumbai": "hardhat deploy --tags mumbai --network mumbai", + "node:hardhat": "hardhat node", + "deploy:hardhat": "hardhat run scripts/deploy.js --network hardhat", + "deploy:mumbai": "hardhat run scripts/deploy.js --network mumbai", "compile": "hardhat compile", "postinstall": "husky install", "prepack": "pinst --disable", @@ -35,13 +35,14 @@ "@nomiclabs/hardhat-etherscan": "^3.1.0", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^4.7.3", + "@openzeppelin/contracts-upgradeable": "^4.8.0", + "@openzeppelin/hardhat-upgrades": "^1.22.0", "@types/mocha": "^10.0.1", "chai": "^4.3.6", "dotenv": "^16.0.2", "ethers": "^5.7.2", "hardhat": "^2.11.2", "hardhat-contract-sizer": "^2.6.1", - "hardhat-deploy": "^0.11.15", "hardhat-gas-reporter": "^1.0.9", "husky": "^8.0.2", "lint-staged": "^13.0.4", diff --git a/scripts/deploy.js b/scripts/deploy.js new file mode 100644 index 0000000..5ccb143 --- /dev/null +++ b/scripts/deploy.js @@ -0,0 +1,53 @@ +const { deployStore } = require('./utils/deploy-store'); +const { getProxyAddress, proxyStore } = require('./utils/proxy-store'); + +const CONTRACT_NAME = 'FleekERC721'; +const NETWORK = hre.network.name; +const ARGUMENTS = [ + 'FleekNFAs', // Collection name + 'FLKNFA', // Collection symbol +]; + +const deploy = async () => { + const Contract = await ethers.getContractFactory(CONTRACT_NAME); + const proxyAddress = await getProxyAddress(CONTRACT_NAME, NETWORK); + + let deployResult; + + try { + if (!proxyAddress) throw new Error('No proxy address found'); + console.log(`Trying to upgrade proxy contract at: "${proxyAddress}"`); + deployResult = await upgrades.upgradeProxy(proxyAddress, Contract); + console.log( + `Contract ${CONTRACT_NAME} upgraded at "${deployResult.address}" by account "${deployResult.signer.address}"` + ); + await deployStore(NETWORK, CONTRACT_NAME, deployResult); + } catch (e) { + if ( + e.message === 'No proxy address found' || + e.message.includes("doesn't look like an ERC 1967 proxy") + ) { + console.log(`Failed to upgrade proxy contract: "${e.message?.trim()}"`); + console.log('Creating new proxy contract...'); + deployResult = await upgrades.deployProxy(Contract, ARGUMENTS); + await deployResult.deployed(); + await proxyStore(CONTRACT_NAME, deployResult.address, hre.network.name); + console.log( + `Contract ${CONTRACT_NAME} deployed at "${deployResult.address}" by account "${deployResult.signer.address}"` + ); + } else { + throw e; + } + + try { + await deployStore(NETWORK, CONTRACT_NAME, deployResult); + } catch (e) { + console.error('Could not write deploy files', e); + } + } +}; + +console.log(':: Starting Deployment ::'); +console.log('Network:', NETWORK); +console.log('Contract:', CONTRACT_NAME); +deploy(); diff --git a/scripts/mint.js b/scripts/mint.js index fe43263..5b0c5c7 100644 --- a/scripts/mint.js +++ b/scripts/mint.js @@ -6,16 +6,14 @@ const params = [ '0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049', // to 'Fleek App', // name 'Description', // description - 'https://fleek.network/fleek-network-logo-minimal.png', // image 'https://fleek.co/', // external url 'fleek.eth', // ens '6ea6ad16c46ae85faced7e50555ff7368422f57', // commit hash 'https://github.com/org/repo', // repo - 'fleek', // author ]; (async () => { - const contract = getContract('FleekERC721'); + const contract = await getContract('FleekERC721'); const transaction = await contract.mint(...params); diff --git a/scripts/tokenURI.js b/scripts/tokenURI.js index b34077e..4792cbf 100644 --- a/scripts/tokenURI.js +++ b/scripts/tokenURI.js @@ -2,7 +2,7 @@ const { getContract } = require('./util'); // TODO: make this arguments -const tokenId = 1; +const tokenId = 0; (async () => { const contract = await getContract('FleekERC721'); diff --git a/scripts/util.js b/scripts/util.js index cda9549..efe7131 100644 --- a/scripts/util.js +++ b/scripts/util.js @@ -1,7 +1,14 @@ module.exports.getContract = async function (contractName) { - const { - address, - } = require(`../deployments/${hre.network.name}/${contractName}.json`); + const proxyDeployments = + require(`../deployments/${hre.network.name}/proxy.json`)[contractName]; - return hre.ethers.getContractAt(contractName, address); + if (!proxyDeployments || !proxyDeployments.length) { + throw new Error( + `No proxy deployments found for "${contractName}" under "${hre.network.name}"` + ); + } + + const latestDeployment = proxyDeployments[0]; + + return hre.ethers.getContractAt(contractName, latestDeployment.address); }; diff --git a/scripts/utils/deploy-store.js b/scripts/utils/deploy-store.js new file mode 100644 index 0000000..5d5009d --- /dev/null +++ b/scripts/utils/deploy-store.js @@ -0,0 +1,49 @@ +const { writeFile } = require('./file'); +const path = require('path'); + +const getDeployFilePath = (network, contractName) => { + return path.resolve( + __dirname, + `../../deployments/${network}/${contractName}.json` + ); +}; + +module.exports.deployStore = async (network, contractName, contract) => { + const filePath = getDeployFilePath(network, contractName); + + const buildArtifact = await hre.artifacts.readArtifact(contractName); + const { + id: buildId, + input: solcInput, + output: solcOutput, + } = await hre.artifacts.getBuildInfo( + `${buildArtifact.sourceName}:${buildArtifact.contractName}` + ); + + const contractOutput = + solcOutput.contracts[buildArtifact.sourceName][contractName]; + + const data = { + timestamp: new Date().toLocaleString('en-US'), + address: contract.address, + transactionHash: contract.deployTransaction.hash, + args: contract.deployTransaction.args, + gasPrice: contract.deployTransaction.gasPrice.toNumber(), + abi: contractOutput.abi, + bytecode: buildArtifact.bytecode, + metadata: contractOutput.metadata, + storageLayout: contractOutput.storageLayout, + }; + + try { + const solcInputsFilePath = + filePath.split('/').slice(0, -1).join('/') + + `/solcInputs/${buildId}.json`; + console.log('Writing deploy files', filePath); + + await writeFile(filePath, JSON.stringify(data, null, 2)); + await writeFile(solcInputsFilePath, JSON.stringify(solcInput, null, 2)); + } catch (err) { + throw `Could not write file: ${err}`; + } +}; diff --git a/scripts/utils/file.js b/scripts/utils/file.js new file mode 100644 index 0000000..fe71e89 --- /dev/null +++ b/scripts/utils/file.js @@ -0,0 +1,20 @@ +const { existsSync, promises: fs } = require('fs'); + +const createFolder = async (filePath) => { + const folderPath = filePath.split('/').slice(0, -1).join('/'); + + if (!existsSync(folderPath)) { + try { + await fs.mkdir(folderPath, { + recursive: true, + }); + } catch (err) { + throw `Could not create network folder: ${err}`; + } + } +}; + +module.exports.writeFile = async (filePath, data) => { + await createFolder(filePath); + return fs.writeFile(filePath, data); +}; diff --git a/scripts/utils/proxy-store.js b/scripts/utils/proxy-store.js new file mode 100644 index 0000000..422e011 --- /dev/null +++ b/scripts/utils/proxy-store.js @@ -0,0 +1,45 @@ +const { existsSync } = require('fs'); +const path = require('path'); +const { writeFile } = require('./file'); + +const getProxyFilePath = (network) => { + return path.resolve(__dirname, `../../deployments/${network}/proxy.json`); +}; + +module.exports.proxyStore = async (contract, proxyAddress, network) => { + const filePath = getProxyFilePath(network); + + const file = existsSync(filePath) ? require(filePath) : {}; + const newRecord = { + address: proxyAddress, + timestamp: new Date().toLocaleString('en-US'), + }; + if (file[contract]) { + file[contract].unshift(newRecord); + } else { + file[contract] = [newRecord]; + } + + try { + console.log('Writing proxy file', filePath); + await writeFile(filePath, JSON.stringify(file, null, 2)); + } catch (err) { + throw `Could not write file: ${err}`; + } +}; + +module.exports.getProxyFilePath = getProxyFilePath; + +module.exports.getProxyAddress = (contract, network) => { + const filePath = getProxyFilePath(network); + + return new Promise((resolve) => { + try { + const proxyList = require(filePath)[contract]; + const lastItem = proxyList[0]; + resolve(lastItem.address); + } catch (err) { + resolve(); + } + }); +}; diff --git a/test/FleekERC721.ts b/test/FleekERC721.ts index d59a391..5c2646f 100644 --- a/test/FleekERC721.ts +++ b/test/FleekERC721.ts @@ -1,6 +1,6 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; describe('FleekERC721', () => { const ROLES = Object.freeze({ @@ -28,10 +28,10 @@ describe('FleekERC721', () => { const [owner, otherAccount] = await ethers.getSigners(); const Contract = await ethers.getContractFactory('FleekERC721'); - const contract = await Contract.deploy( + const contract = await upgrades.deployProxy(Contract, [ COLLECTION_PARAMS.name, - COLLECTION_PARAMS.symbol - ); + COLLECTION_PARAMS.symbol, + ]); return { owner, otherAccount, contract }; }; diff --git a/test/deploy/proxy-store.ts b/test/deploy/proxy-store.ts new file mode 100644 index 0000000..55bde0f --- /dev/null +++ b/test/deploy/proxy-store.ts @@ -0,0 +1,36 @@ +import { expect } from 'chai'; +import { proxyStore, getProxyFilePath } from '../../scripts/utils/proxy-store'; +import fs from 'fs/promises'; + +describe('Proxy Store', () => { + const network = 'test'; + const contractName = 'FleekERC721'; + const proxyAddress = '0x91A425C1CA320A99a09BE1bee114Fce5d30153d9'; + + afterEach(async () => { + await fs.rm(getProxyFilePath(network)); + }); + + it('should store the data', async () => { + await proxyStore(contractName, proxyAddress, network); + const file = require(getProxyFilePath(network)); + expect(file[contractName]).to.eql([ + { address: proxyAddress, timestamp: new Date().toLocaleString('en-US') }, + ]); + }); + + it('should update the data', async () => { + const newProxyAddress = '0xB8594DC01580884AD69FE5d78EDEA5e66BeB5fFA'; + await proxyStore(contractName, proxyAddress, network); + await proxyStore(contractName, newProxyAddress, network); + const file = require(getProxyFilePath(network)); + + expect(file[contractName]).to.eql([ + { + address: newProxyAddress, + timestamp: new Date().toLocaleString('en-US'), + }, + { address: proxyAddress, timestamp: new Date().toLocaleString('en-US') }, + ]); + }); +}); diff --git a/test/deploy/proxy.ts b/test/deploy/proxy.ts new file mode 100644 index 0000000..afc1ed2 --- /dev/null +++ b/test/deploy/proxy.ts @@ -0,0 +1,20 @@ +import { expect } from 'chai'; +import { ethers, upgrades } from 'hardhat'; + +describe('Proxy', function () { + it('FleekERC721', async () => { + const Contract = await ethers.getContractFactory('FleekERC721'); + const ContractV2 = await ethers.getContractFactory('FleekERC721'); + + const instance = await upgrades.deployProxy(Contract, [ + 'Collection Name', + 'SYMBOL', + ]); + const upgraded = await upgrades.upgradeProxy(instance.address, ContractV2); + + const name = await upgraded.name(); + const symbol = await upgraded.symbol(); + expect(name).to.equal('Collection Name'); + expect(symbol).to.equal('SYMBOL'); + }); +}); diff --git a/test/foundry/apps.t.sol b/test/foundry/apps.t.sol index d24854f..79173d3 100644 --- a/test/foundry/apps.t.sol +++ b/test/foundry/apps.t.sol @@ -11,7 +11,8 @@ contract FleekTest is Test { string constant FLEEK_AP_URL = "https://fleek_cloned.xyz"; function setUp() public { - fleekContract = new FleekERC721("Test Contract", "FLKAPS"); + fleekContract = new FleekERC721(); + fleekContract.initialize("Test Contract", "FLKAPS"); } function testName() public { diff --git a/yarn.lock b/yarn.lock index 6bd7275..03c7d8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1187,11 +1187,39 @@ dependencies: "@types/bignumber.js" "^5.0.0" +"@openzeppelin/contracts-upgradeable@^4.8.0": + version "4.8.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0.tgz#26688982f46969018e3ed3199e72a07c8d114275" + integrity sha512-5GeFgqMiDlqGT8EdORadp1ntGF0qzWZLmEY7Wbp/yVhN7/B3NNzCxujuI77ktlyG81N3CUZP8cZe3ZAQ/cW10w== + "@openzeppelin/contracts@^4.7.3": version "4.8.0" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.0.tgz#6854c37df205dd2c056bdfa1b853f5d732109109" integrity sha512-AGuwhRRL+NaKx73WKRNzeCxOCOCxpaqF+kp8TJ89QzAipSwZy/NoflkWaL9bywXFRhIzXt8j38sfF7KBKCPWLw== +"@openzeppelin/hardhat-upgrades@^1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.22.0.tgz#2a432c72a428a9f277201646bc1a248021538f06" + integrity sha512-1qyZnDaxl0C8tne7ykNRa/fxw3FrNCY2M3fGuCiQW5DDkJoXhLgm3JVsXwl6X7q9mQSrik4vgBbI3ErmxmZTYg== + dependencies: + "@openzeppelin/upgrades-core" "^1.20.0" + chalk "^4.1.0" + debug "^4.1.1" + proper-lockfile "^4.1.1" + +"@openzeppelin/upgrades-core@^1.20.0": + version "1.20.6" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.20.6.tgz#74f43d600151b8fda6e2d375f46ae0da55922620" + integrity sha512-KWdtlahm+iunlAlzLsdpBueanwEx0LLPfAkDL1p0C4SPjMiUqHHFlyGtmmWwdiqDpJ//605vfwkd5RqfnFrHSg== + dependencies: + cbor "^8.0.0" + chalk "^4.1.0" + compare-versions "^5.0.0" + debug "^4.1.1" + ethereumjs-util "^7.0.3" + proper-lockfile "^4.1.1" + solidity-ast "^0.4.15" + "@peculiar/asn1-schema@^2.1.6", "@peculiar/asn1-schema@^2.3.0": version "2.3.3" resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz#21418e1f3819e0b353ceff0c2dad8ccb61acd777" @@ -1511,7 +1539,7 @@ dependencies: "@types/node" "*" -"@types/qs@^6.2.31", "@types/qs@^6.9.7": +"@types/qs@^6.2.31": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== @@ -1881,13 +1909,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2231,7 +2252,7 @@ catering@^2.1.0, catering@^2.1.1: resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== -cbor@^8.1.0: +cbor@^8.0.0, cbor@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== @@ -2267,7 +2288,7 @@ chalk@^2.0.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2556,6 +2577,11 @@ common-tags@1.8.2: resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== +compare-versions@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-5.0.3.tgz#a9b34fea217472650ef4a2651d905f42c28ebfd7" + integrity sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2783,7 +2809,7 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -3006,11 +3032,6 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -encode-utf8@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" - integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3023,7 +3044,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enquirer@^2.3.0, enquirer@^2.3.6: +enquirer@^2.3.0: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== @@ -3284,7 +3305,7 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -3310,7 +3331,7 @@ ethers@^4.0.40: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.5.3, ethers@^5.7.2: +ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -3567,14 +3588,7 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -fmix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" - integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w== - dependencies: - imul "^1.0.0" - -follow-redirects@^1.12.1, follow-redirects@^1.14.0: +follow-redirects@^1.12.1: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -3619,15 +3633,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -3676,15 +3681,6 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" - integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -3975,7 +3971,7 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -4011,11 +4007,6 @@ graphql-ws@5.11.2: resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.11.2.tgz#d5e0acae8b4d4a4cf7be410a24135cfcefd7ddc0" integrity sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w== -graphql@^16.6.0: - version "16.6.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" - integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== - growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -4054,25 +4045,6 @@ hardhat-contract-sizer@^2.6.1: chalk "^4.0.0" cli-table3 "^0.6.0" -hardhat-deploy@^0.11.15: - version "0.11.22" - resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487" - integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ== - dependencies: - "@types/qs" "^6.9.7" - axios "^0.21.1" - chalk "^4.1.2" - chokidar "^3.5.2" - debug "^4.3.2" - enquirer "^2.3.6" - ethers "^5.5.3" - form-data "^4.0.0" - fs-extra "^10.0.0" - match-all "^1.2.6" - murmur-128 "^0.2.1" - qs "^6.9.4" - zksync-web3 "^0.8.1" - hardhat-gas-reporter@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz#9a2afb354bc3b6346aab55b1c02ca556d0e16450" @@ -4368,11 +4340,6 @@ import-from@4.0.0: resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2" integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ== -imul@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" - integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA== - indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -4784,15 +4751,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== - dependencies: - universalify "^2.0.0" - optionalDependencies: - graceful-fs "^4.1.6" - jsonify@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" @@ -5072,11 +5030,6 @@ markdown-table@^1.1.3: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== -match-all@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" - integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== - mcl-wasm@^0.7.1: version "0.7.9" resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" @@ -5443,15 +5396,6 @@ multihashes@^0.4.15, multihashes@~0.4.15: multibase "^0.7.0" varint "^5.0.0" -murmur-128@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" - integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== - dependencies: - encode-utf8 "^1.0.2" - fmix "^0.1.0" - imul "^1.0.0" - mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -5959,6 +5903,15 @@ promise@^8.0.0: dependencies: asap "~2.0.6" +proper-lockfile@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -6014,7 +5967,7 @@ pvutils@^1.1.3: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== -qs@6.11.0, qs@^6.4.0, qs@^6.7.0, qs@^6.9.4: +qs@6.11.0, qs@^6.4.0, qs@^6.7.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== @@ -6276,6 +6229,11 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -6624,6 +6582,11 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" +solidity-ast@^0.4.15: + version "0.4.40" + resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.40.tgz#182709271b4e55efb34e2da934dfaa96ee0cf40b" + integrity sha512-M8uLBT2jgFB7B0iVAC5a2l71J8vim7aEm03AZkaHbDqyrl1pE+i5PriMEw6WlwGfHp3/Ym7cn9BqvVLQgRk+Yw== + solidity-comments-extractor@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" @@ -7188,11 +7151,6 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== -universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== - unixify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" @@ -7906,8 +7864,3 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zksync-web3@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14" - integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw==