Address Contract Verified
Address
0x543D43F390b7d681513045e8a85707438c463d80
Balance
0 ETH
Nonce
1
Code Size
22344 bytes
Creator
0x4CDE318d...91e8 at tx 0x128e8a2f...ea841f
Indexed Transactions
0
Contract Bytecode
22344 bytes
0x60806040526004361061044a5760003560e01c80638ecc808311610234578063c8e7e6191161012e578063e1de6710116100b6578063ea3740e81161007a578063ea3740e814610e2a578063f04307b114610e4b578063f2fde38b14610e5e578063fa6a6f6b14610e7e578063fdda339114610e9e57600080fd5b8063e1de671014610d73578063e1e2022014610da7578063e24fe16014610dbd578063e43fc99214610dea578063e985e9c514610e0a57600080fd5b8063d9c4870e116100fd578063d9c4870e14610cb9578063dbdff2c114610ced578063dc04602a14610d02578063e042e98c14610d22578063e0ba2caf14610d4257600080fd5b8063c8e7e61914610c2f578063d218d95d14610c4f578063d5abeb0114610c6f578063d5d0671d14610ca357600080fd5b8063a3c12228116101bc578063b88d4fde11610180578063b88d4fde14610ba4578063bcba693914610bc4578063bfab3db914610be4578063c128aace14610bf9578063c87b56dd14610c0f57600080fd5b8063a3c1222814610b21578063aab99fa014610b41578063ac1d1c0914610b57578063b2acde9414610b6d578063b313376714610b8357600080fd5b806396789548116102035780639678954814610a9157806398bdf6f514610aa457806399ee0f5f14610aba578063a05bb3c214610aee578063a22cb46514610b0157600080fd5b80638ecc808314610a275780638ef79e9114610a3c578063952bc52514610a5c57806395d89b4114610a7c57600080fd5b806342842e0e1161034557806370a08231116102cd5780637ea0f46d116102915780637ea0f46d1461099957806382776b9c146109b95780638456cb59146109ce57806389852715146109e35780638da5cb5b14610a0457600080fd5b806370a08231146108e0578063715018a614610900578063722c632c146109155780637ab7a9fe146109455780637dec8b621461097957600080fd5b806356d8280e1161031457806356d8280e1461083d57806359081cec1461085e5780635c975abb146108745780636352211e1461088c5780636817c76c146108ac57600080fd5b806342842e0e146107c757806342966c68146107e75780634c99007d1461080757806352357fcf1461081d57600080fd5b806318160ddd116103d357806323b872dd1161039757806323b872dd146107095780632a55205a146107295780632b1063c6146107685780632f2fd1701461079d5780633f4ba83a146107b257600080fd5b806318160ddd146106665780631e427660146106895780631e5b2874146106a95780631fe543e3146106c957806321fb4a44146106e957600080fd5b806306fdde031161041a57806306fdde03146105b7578063081812fc146105d9578063095ea7b31461061157806312cdee591461063157806316fb27fe1461065157600080fd5b80629ee39c1461053857806301ffc9a71461055857806302eb79761461058d578063051efeb9146105a257600080fd5b36610533576000341161048d5760405162461bcd60e51b815260206004820152600660248201526509cde408aa8960d31b60448201526064015b60405180910390fd5b336001600160a01b037f0000000000000000000000000b4e6f5c38a5e0fa2ea528bac2055e7304f82fef1614806104e5575060065461010090046001600160a01b03166001600160a01b0316336001600160a01b0316145b6105315760405162461bcd60e51b815260206004820152601960248201527f4f6e6c79206f776e6572206f722062656e6566696369617279000000000000006044820152606401610484565b005b600080fd5b34801561054457600080fd5b5061053161055336600461467d565b610ed2565b34801561056457600080fd5b506105786105733660046146b0565b610f24565b60405190151581526020015b60405180910390f35b34801561059957600080fd5b50610531610f4f565b3480156105ae57600080fd5b50610578610f94565b3480156105c357600080fd5b506105cc610ffd565b6040516105849190614725565b3480156105e557600080fd5b506105f96105f4366004614738565b61108f565b6040516001600160a01b039091168152602001610584565b34801561061d57600080fd5b5061053161062c366004614751565b611124565b34801561063d57600080fd5b5061053161064c366004614828565b611239565b34801561065d57600080fd5b506105316112d3565b34801561067257600080fd5b5061067b611318565b604051908152602001610584565b34801561069557600080fd5b506105316106a43660046148b4565b61132a565b3480156106b557600080fd5b506105316106c436600461467d565b611469565b3480156106d557600080fd5b506105316106e43660046148ff565b61150b565b3480156106f557600080fd5b50610531610704366004614738565b61158f565b34801561071557600080fd5b506105316107243660046149b0565b6115ee565b34801561073557600080fd5b506107496107443660046149f1565b611620565b604080516001600160a01b039093168352602083019190915201610584565b34801561077457600080fd5b507f0000000000000000000000000000000000000000000000000000000062f141104211610578565b3480156107a957600080fd5b50610531611659565b3480156107be57600080fd5b5061053161169e565b3480156107d357600080fd5b506105316107e23660046149b0565b6116d8565b3480156107f357600080fd5b50610531610802366004614738565b6116f3565b34801561081357600080fd5b5061067b600f5481565b34801561082957600080fd5b50610531610838366004614738565b611717565b34801561084957600080fd5b5060105461057890600160b81b900460ff1681565b34801561086a57600080fd5b5061067b60185481565b34801561088057600080fd5b5060065460ff16610578565b34801561089857600080fd5b506105f96108a7366004614738565b611776565b3480156108b857600080fd5b5061067b7f00000000000000000000000000000000000000000000000002c68af0bb14000081565b3480156108ec57600080fd5b5061067b6108fb36600461467d565b6117ed565b34801561090c57600080fd5b50610531611874565b34801561092157600080fd5b50610935610930366004614a13565b6118ae565b6040516105849493929190614a67565b34801561095157600080fd5b5061067b7f0000000000000000000000000000000000000000000000000000000062f1411081565b34801561098557600080fd5b50610935610994366004614aa5565b6119be565b3480156109a557600080fd5b50601c546105f9906001600160a01b031681565b3480156109c557600080fd5b50610531611ad0565b3480156109da57600080fd5b50610531611b6a565b3480156109ef57600080fd5b5060105461057890600160a01b900460ff1681565b348015610a1057600080fd5b5060065461010090046001600160a01b03166105f9565b348015610a3357600080fd5b506105cc611c49565b348015610a4857600080fd5b50610531610a57366004614b00565b611cd7565b348015610a6857600080fd5b50610531610a77366004614738565b611d69565b348015610a8857600080fd5b506105cc611dc8565b610531610a9f366004614b71565b611dd7565b348015610ab057600080fd5b5061067b600e5481565b348015610ac657600080fd5b5061067b7f000000000000000000000000000000000000000000000000000000000000009681565b610531610afc366004614bce565b611ffc565b348015610b0d57600080fd5b50610531610b1c366004614c5e565b6122be565b348015610b2d57600080fd5b50610531610b3c366004614c97565b6122c9565b348015610b4d57600080fd5b5061067b60165481565b348015610b6357600080fd5b5061067b60155481565b348015610b7957600080fd5b5061067b600c5481565b348015610b8f57600080fd5b5060105461057890600160a81b900460ff1681565b348015610bb057600080fd5b50610531610bbf366004614ce9565b6124bd565b348015610bd057600080fd5b50610531610bdf366004614751565b6124ef565b348015610bf057600080fd5b50610531612545565b348015610c0557600080fd5b5061067b60135481565b348015610c1b57600080fd5b506105cc610c2a366004614738565b61262d565b348015610c3b57600080fd5b50610531610c4a366004614738565b612806565b348015610c5b57600080fd5b50610531610c6a366004614d68565b612865565b348015610c7b57600080fd5b5061067b7f0000000000000000000000000000000000000000000000000000000000004e2081565b348015610caf57600080fd5b5061067b60115481565b348015610cc557600080fd5b506105f97f0000000000000000000000000b4e6f5c38a5e0fa2ea528bac2055e7304f82fef81565b348015610cf957600080fd5b5061067b6128c2565b348015610d0e57600080fd5b50610935610d1d366004614d91565b612a3b565b348015610d2e57600080fd5b50610531610d3d366004614738565b612b5e565b348015610d4e57600080fd5b50610d62610d5d366004614df4565b612b93565b604051610584959493929190614e5d565b348015610d7f57600080fd5b5061067b7f000000000000000000000000000000000000000000000000000000000000001581565b348015610db357600080fd5b5061067b601a5481565b348015610dc957600080fd5b5061067b610dd8366004614738565b60176020526000908152604090205481565b348015610df657600080fd5b50610531610e05366004614ea1565b612d00565b348015610e1657600080fd5b50610578610e25366004614f09565b612f43565b348015610e3657600080fd5b5060105461057890600160b01b900460ff1681565b610531610e59366004614f37565b612f71565b348015610e6a57600080fd5b50610531610e7936600461467d565b6131cd565b348015610e8a57600080fd5b50610935610e99366004614f96565b61326b565b348015610eaa57600080fd5b5061067b7f0000000000000000000000000000000000000000000000000000000062ee9e1081565b6006546001600160a01b03610100909104163314610f025760405162461bcd60e51b815260040161048490615003565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160e01b0319821663152a902d60e11b1480610f495750610f4982613390565b92915050565b6006546001600160a01b03610100909104163314610f7f5760405162461bcd60e51b815260040161048490615003565b6010805460ff60a81b1916600160a81b179055565b6000610fc160017f0000000000000000000000000000000000000000000000000000000062ee9e1061504e565b42118015610ff85750610ff57f0000000000000000000000000000000000000000000000000000000062f141106001615065565b42105b905090565b60606000805461100c9061507d565b80601f01602080910402602001604051908101604052809291908181526020018280546110389061507d565b80156110855780601f1061105a57610100808354040283529160200191611085565b820191906000526020600020905b81548152906001019060200180831161106857829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b03166111085760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610484565b506000908152600460205260409020546001600160a01b031690565b600061112f82611776565b9050806001600160a01b0316836001600160a01b03160361119c5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610484565b336001600160a01b03821614806111b857506111b88133612f43565b61122a5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610484565b61123483836133e0565b505050565b6006546001600160a01b036101009091041633146112695760405162461bcd60e51b815260040161048490615003565b601054600160b81b900460ff16156112c35760405162461bcd60e51b815260206004820152601760248201527f506c61636520686f6c64657220555249206c6f636b65640000000000000000006044820152606401610484565b600b6112cf82826150fd565b5050565b6006546001600160a01b036101009091041633146113035760405162461bcd60e51b815260040161048490615003565b6010805460ff60b81b1916600160b81b179055565b6000600f54600e54610ff8919061504e565b601054600160a81b900460ff16156113545760405162461bcd60e51b8152600401610484906151bc565b6006546001600160a01b036101009091041633146113845760405162461bcd60e51b815260040161048490615003565b7f000000000000000000000000000000000000000000000000000000000000001582146113f35760405162461bcd60e51b815260206004820152601d60248201527f436f6d6d756e697479206c656e67746820646f65736e74206d617463680000006044820152606401610484565b601681905560005b7f000000000000000000000000000000000000000000000000000000000000001581101561146357838382818110611435576114356151e2565b600084815260176020908152604090912091029290920135909155508061145b816151f8565b9150506113fb565b50505050565b6006546001600160a01b036101009091041633146114995760405162461bcd60e51b815260040161048490615003565b601054600160b01b900460ff16156114e95760405162461bcd60e51b815260206004820152601360248201527213185b99081859191c995cdcc81b1bd8dad959606a1b6044820152606401610484565b601c80546001600160a01b0319166001600160a01b0392909216919091179055565b336001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e6990916146115855760405163073e64fd60e21b81523360048201526001600160a01b037f000000000000000000000000271682deb8c4e0901d1a1550ad2e64d568e69909166024820152604401610484565b6112cf828261344e565b601054600160a81b900460ff16156115b95760405162461bcd60e51b8152600401610484906151bc565b6006546001600160a01b036101009091041633146115e95760405162461bcd60e51b815260040161048490615003565b601555565b6115f9335b826134b4565b6116155760405162461bcd60e51b815260040161048490615211565b61123483838361358b565b6000806000612710600d54856116369190615262565b6116409190615297565b6010546001600160a01b031693509150505b9250929050565b6006546001600160a01b036101009091041633146116895760405162461bcd60e51b815260040161048490615003565b6010805460ff60b01b1916600160b01b179055565b6006546001600160a01b036101009091041633146116ce5760405162461bcd60e51b815260040161048490615003565b6116d6613736565b565b611234838383604051806020016040528060008152506124bd565b6116fc816137c9565b6001600f600082825461170f9190615065565b909155505050565b601054600160a81b900460ff16156117415760405162461bcd60e51b8152600401610484906151bc565b6006546001600160a01b036101009091041633146117715760405162461bcd60e51b815260040161048490615003565b601355565b6000818152600260205260408120546001600160a01b031680610f495760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610484565b60006001600160a01b0382166118585760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610484565b506001600160a01b031660009081526003602052604090205490565b6006546001600160a01b036101009091041633146118a45760405162461bcd60e51b815260040161048490615003565b6116d66000613840565b6000806000606060006118c08861389a565b90506119038787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060155491508490506138d4565b151560000361194d575050604080518082019091526019815278111a5c9958dd081b5a5b9d081c1c9bdbd9881a5b9d985b1a59603a1b6020820152869350839250600091506119b5565b6001600160a01b0388166000908152601b602052604090205460ff16156119995787886000604051806060016040528060228152602001615643602291399450945094509450506119b5565b5050604080516020810190915260008152869350839250600191505b93509350935093565b6000806000606060006119d1888a6138ec565b9050611a148787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060115491508490506138d4565b1515600003611a5d57505060408051808201909152601881527710db185a5b481b5a5b9d081c1c9bdbd9881a5b9d985b1a5960421b602082015287935083925060009150611ac5565b6001600160a01b03891660009081526012602052604090205460ff1615611aa9578889600060405180606001604052806021815260200161569860219139945094509450945050611ac5565b5050604080516020810190915260008152879350839250600191505b945094509450949050565b6006546001600160a01b03610100909104163314611b005760405162461bcd60e51b815260040161048490615003565b601054600160a01b900460ff1615611b555760405162461bcd60e51b8152602060048201526018602482015277151bdad95b8818985cd948155492481a5cc81b1bd8dad95960421b6044820152606401610484565b6010805460ff60a01b1916600160a01b179055565b6006546001600160a01b03610100909104163314611b9a5760405162461bcd60e51b815260040161048490615003565b7f0000000000000000000000000000000000000000000000000000000062ee9e101580611bff5750601a54611bd29062015180615262565b611bfc907f0000000000000000000000000000000000000000000000000000000062ee9e10615065565b42105b611c415760405162461bcd60e51b815260206004820152601360248201527214185d5cd94818dd5d1bd999881c185cdcd959606a1b6044820152606401610484565b6116d6613935565b600b8054611c569061507d565b80601f0160208091040260200160405190810160405280929190818152602001828054611c829061507d565b8015611ccf5780601f10611ca457610100808354040283529160200191611ccf565b820191906000526020600020905b815481529060010190602001808311611cb257829003601f168201915b505050505081565b6006546001600160a01b03610100909104163314611d075760405162461bcd60e51b815260040161048490615003565b601054600160a01b900460ff1615611d5c5760405162461bcd60e51b8152602060048201526018602482015277151bdad95b8818985cd948155492481a5cc81b1bd8dad95960421b6044820152606401610484565b600a6112348284836152ab565b601054600160a81b900460ff1615611d935760405162461bcd60e51b8152600401610484906151bc565b6006546001600160a01b03610100909104163314611dc35760405162461bcd60e51b815260040161048490615003565b601855565b60606001805461100c9061507d565b817f0000000000000000000000000000000000000000000000000000000000004e2081600e54611e079190615065565b1115611e255760405162461bcd60e51b81526004016104849061536b565b611e2f8284615262565b3414611e4d5760405162461bcd60e51b815260040161048490615398565b601854600003611e9f5760405162461bcd60e51b815260206004820152601e60248201527f436f6d706c6574696f6e206d65726b6c6520726f6f74206e6f742073657400006044820152606401610484565b6000611eac8733856139b0565b9050611eef8686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060185491508490506138d4565b611f3b5760405162461bcd60e51b815260206004820152601e60248201527f436f6d706c6574696f6e3a206d696e742070726f6f6620696e76616c696400006044820152606401610484565b336000908152601960205260409020548790611f58908690615065565b1115611fc45760405162461bcd60e51b815260206004820152603560248201527f436f6d706c6574696f6e3a2052657175657374696e67206d6f7265207468616e604482015274103932b6b0b4b734b7339030b63637b1b0ba34b7b760591b6064820152608401610484565b3360009081526019602052604081208054869290611fe3908490615065565b90915550611ff3905033856139fe565b50505050505050565b612004610f94565b6120465760405162461bcd60e51b815260206004820152601360248201527214dd1859d9480c481b5a5b9d0818db1bdcd959606a1b6044820152606401610484565b600c546000036120985760405162461bcd60e51b815260206004820152601c60248201527f436f6d6d756e6974792072616e646f6d6e657373206e6f7420736574000000006044820152606401610484565b60017f0000000000000000000000000000000000000000000000000000000000004e2081600e546120c99190615065565b11156120e75760405162461bcd60e51b81526004016104849061536b565b7f00000000000000000000000000000000000000000000000002c68af0bb14000034146121265760405162461bcd60e51b815260040161048490615398565b6016546000036121785760405162461bcd60e51b815260206004820152601d60248201527f436f6d6d756e697479206d65726b6c6520726f6f74206e6f74207365740000006044820152606401610484565b6121b783838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613a3d915050565b60006121c4888833613b61565b90506122078686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060165491508490506138d4565b6122535760405162461bcd60e51b815260206004820152601c60248201527f436f6d6d756e697479206d696e742070726f6f6620696e76616c6964000000006044820152606401610484565b61225d8789613b90565b6122a95760405162461bcd60e51b815260206004820152601c60248201527f5468697320706f736974696f6e20686173206d6973736564206f7574000000006044820152606401610484565b6122b4338585613c8f565b5050505050505050565b6112cf338383613d9e565b807f0000000000000000000000000000000000000000000000000000000000004e2081600e546122f99190615065565b11156123175760405162461bcd60e51b81526004016104849061536b565b6013546000036123645760405162461bcd60e51b8152602060048201526018602482015277135a5b9d081b595c9adb19481c9bdbdd081b9bdd081cd95d60421b6044820152606401610484565b600061237086336138ec565b90506123b38585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060135491508490506138d4565b6123ff5760405162461bcd60e51b815260206004820152601c60248201527f54726561737572793a206d696e742070726f6f6620696e76616c6964000000006044820152606401610484565b33600090815260146020526040902054869061241c908590615065565b11156124865760405162461bcd60e51b815260206004820152603360248201527f54726561737572793a2052657175657374696e67206d6f7265207468616e207260448201527232b6b0b4b734b7339030b63637b1b0ba34b7b760691b6064820152608401610484565b33600090815260146020526040812080548592906124a5908490615065565b909155506124b5905033846139fe565b505050505050565b6124c733836134b4565b6124e35760405162461bcd60e51b815260040161048490615211565b61146384848484613e6c565b6006546001600160a01b0361010090910416331461251f5760405162461bcd60e51b815260040161048490615003565b6006546112cf9061010090046001600160a01b03166001600160a01b0384169083613e9f565b6006546001600160a01b036101009091041633146125755760405162461bcd60e51b815260040161048490615003565b60007f0000000000000000000000000b4e6f5c38a5e0fa2ea528bac2055e7304f82fef6001600160a01b03164760405160006040518083038185875af1925050503d80600081146125e2576040519150601f19603f3d011682016040523d82523d6000602084013e6125e7565b606091505b505090508061262a5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610484565b50565b6000818152600260205260409020546060906001600160a01b03166126ac5760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201526e3732bc34b9ba32b73a103a37b5b2b760891b6064820152608401610484565b601c546001600160a01b03161561272e57601c5460405163096f4b5160e41b8152600481018490526001600160a01b03909116906396f4b51090602401600060405180830381865afa158015612706573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f4991908101906153cf565b600a805461273b9061507d565b15905061277457600a61274d83613ef1565b60405160200161275e929190615445565b6040516020818303038152906040529050919050565b600b80546127819061507d565b80601f01602080910402602001604051908101604052809291908181526020018280546127ad9061507d565b80156127fa5780601f106127cf576101008083540402835291602001916127fa565b820191906000526020600020905b8154815290600101906020018083116127dd57829003601f168201915b50505050509050919050565b601054600160a81b900460ff16156128305760405162461bcd60e51b8152600401610484906151bc565b6006546001600160a01b036101009091041633146128605760405162461bcd60e51b815260040161048490615003565b601155565b6006546001600160a01b036101009091041633146128955760405162461bcd60e51b815260040161048490615003565b600780546001600160401b03909216600160a01b0267ffffffffffffffff60a01b19909216919091179055565b6006546000906001600160a01b036101009091041633146128f55760405162461bcd60e51b815260040161048490615003565b6016546000036129405760405162461bcd60e51b815260206004820152601660248201527510dbdb5b5d5b9a5d1e481b1a5cdd081b9bdd081cd95d60521b6044820152606401610484565b600c54156129815760405162461bcd60e51b815260206004820152600e60248201526d14985b991bdb5b995cdcc81cd95d60921b6044820152606401610484565b6007546008546009546040516305d3b1d360e41b81526004810192909252600160a01b83046001600160401b03166024830152640100000000810461ffff16604483015263ffffffff808216606484015266010000000000009091041660848201526001600160a01b0390911690635d3b1d309060a4016020604051808303816000875af1158015612a17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff891906154dc565b600080600060606000612a4e898b6138ec565b9050612a918888808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060135491508490506138d4565b1515600003612adf57505060408051808201909152601c81527f54726561737572793a206d696e742070726f6f6620696e76616c696400000000602082015288935083925060009150612b52565b6001600160a01b038a166000908152601460205260409020548990612b05908890615065565b1115612b3657898a600060405180606001604052806033815260200161566560339139945094509450945050612b52565b5050604080516020810190915260008152889350839250600191505b95509550955095915050565b6006546001600160a01b03610100909104163314612b8e5760405162461bcd60e51b815260040161048490615003565b600d55565b6000806060600080612ba6888a8c613b61565b9150612be98787808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060165491508590506138d4565b1515600003612c36575060408051808201909152601c81527f436f6d6d756e697479206d696e742070726f6f6620696e76616c696400000000602082015289945060009350915083612cf3565b6001600160a01b038a166000908152601b602052604090205460ff1615612c8657896000838c6040518060600160405280602581526020016156ee60259139919094509450945094509450612cf3565b612c908989613b90565b612cd8575060408051808201909152601c81527f5468697320706f736974696f6e20686173206d6973736564206f757400000000602082015289945060009350915083612cf3565b50604080516020810190915260008152899450600193509150835b9550955095509550959050565b847f0000000000000000000000000000000000000000000000000000000000004e2081600e54612d309190615065565b1115612d4e5760405162461bcd60e51b81526004016104849061536b565b601154600003612d9b5760405162461bcd60e51b8152602060048201526018602482015277135a5b9d081b595c9adb19481c9bdbdd081b9bdd081cd95d60421b6044820152606401610484565b612dd98383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508a9250613a3d915050565b6000612de587336138ec565b9050612e288686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060115491508490506138d4565b612e6f5760405162461bcd60e51b815260206004820152601860248201527710db185a5b481b5a5b9d081c1c9bdbd9881a5b9d985b1a5960421b6044820152606401610484565b3360009081526012602052604090205460ff1615612ed95760405162461bcd60e51b815260206004820152602160248201527f436c61696d3a20416464726573732068617320616c7265616479206d696e74656044820152601960fa1b6064820152608401610484565b336000818152601260205260409020805460ff19166001179055612efd90886139fe565b7f302c37e6ef624a63ae3d7d8bc4409b3d5c1ce5d6d4d25b067b57c242be4320ce33888686604051612f32949392919061552b565b60405180910390a150505050505050565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b612f79610f94565b612fbb5760405162461bcd60e51b815260206004820152601360248201527214dd1859d9480c481b5a5b9d0818db1bdcd959606a1b6044820152606401610484565b600c5460000361300d5760405162461bcd60e51b815260206004820152601c60248201527f436f6d6d756e6974792072616e646f6d6e657373206e6f7420736574000000006044820152606401610484565b60017f0000000000000000000000000000000000000000000000000000000000004e2081600e5461303e9190615065565b111561305c5760405162461bcd60e51b81526004016104849061536b565b7f00000000000000000000000000000000000000000000000002c68af0bb140000341461309b5760405162461bcd60e51b815260040161048490615398565b6015546000036130ed5760405162461bcd60e51b815260206004820152601a60248201527f446972656374206d65726b6c6520726f6f74206e6f74207365740000000000006044820152606401610484565b61312c83838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525060019250613a3d915050565b60006131373361389a565b905061317a8686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060155491508490506138d4565b6131c25760405162461bcd60e51b8152602060048201526019602482015278111a5c9958dd081b5a5b9d081c1c9bdbd9881a5b9d985b1a59603a1b6044820152606401610484565b6124b5338585613c8f565b6006546001600160a01b036101009091041633146131fd5760405162461bcd60e51b815260040161048490615003565b6001600160a01b0381166132625760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610484565b61262a81613840565b60008060006060600061327f8a8c886139b0565b90506132c28989808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060185491508490506138d4565b151560000361331057505060408051808201909152601e81527f436f6d706c6574696f6e3a206d696e742070726f6f6620696e76616c69640000602082015289935083925060009150613383565b6001600160a01b038b166000908152601960205260409020548a90613336908990615065565b1115613367578a8b60006040518060600160405280603581526020016156b960359139945094509450945050613383565b5050604080516020810190915260008152899350839250600191505b9650965096509692505050565b60006001600160e01b031982166380ac58cd60e01b14806133c157506001600160e01b03198216635b5e139f60e01b145b80610f4957506301ffc9a760e01b6001600160e01b0319831614610f49565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061341582611776565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600c541561348f5760405162461bcd60e51b815260206004820152600e60248201526d14985b991bdb5b995cdcc81cd95d60921b6044820152606401610484565b806000815181106134a2576134a26151e2565b6020026020010151600c819055505050565b6000818152600260205260408120546001600160a01b031661352d5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610484565b600061353883611776565b9050806001600160a01b0316846001600160a01b031614806135735750836001600160a01b03166135688461108f565b6001600160a01b0316145b8061358357506135838185612f43565b949350505050565b826001600160a01b031661359e82611776565b6001600160a01b0316146136065760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610484565b6001600160a01b0382166136685760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610484565b613673838383613ff1565b61367e6000826133e0565b6001600160a01b03831660009081526003602052604081208054600192906136a790849061504e565b90915550506001600160a01b03821660009081526003602052604081208054600192906136d5908490615065565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60065460ff1661377f5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610484565b6006805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6137d2336115f3565b6138375760405162461bcd60e51b815260206004820152603060248201527f4552433732314275726e61626c653a2063616c6c6572206973206e6f74206f7760448201526f1b995c881b9bdc88185c1c1c9bdd995960821b6064820152608401610484565b61262a81614037565b600680546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6040516001600160601b0319606083901b166020820152600090603401604051602081830303815290604052805190602001209050919050565b6000826138e185846140de565b1490505b9392505050565b6000828260405160200161391792919091825260601b6001600160601b031916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b60065460ff161561397b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610484565b6006805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586137ac3390565b60408051602081018590526001600160601b0319606085901b1691810191909152605481018290526000906074015b6040516020818303038152906040528051906020012090509392505050565b600e5460005b82811015613a3557613a16848361418a565b613a21600183615065565b915080613a2d816151f8565b915050613a04565b50600e555050565b7f0000000000000000000000000000000000000000000000000000000000000015825114613abf5760405162461bcd60e51b815260206004820152602960248201527f566f746520617272617920646f6573206e6f74206d6174636820636f6d6d756e6044820152681a5d1e4818dbdd5b9d60ba1b6064820152608401610484565b6000805b8351811015613b0557838181518110613ade57613ade6151e2565b602002602001015182613af19190615065565b915080613afd816151f8565b915050613ac3565b508181146112345760405162461bcd60e51b815260206004820152602360248201527f566f74657320646f206e6f74206d61746368206d696e74696e67207175616e7460448201526269747960e81b6064820152608401610484565b6040805160208101859052908101839052606082811b6001600160601b031916908201526000906074016139df565b60008181526017602052604081205480613bdd5760405162461bcd60e51b815260206004820152600e60248201526d13195b99dd1a081b9bdd081cd95d60921b6044820152606401610484565b7f0000000000000000000000000000000000000000000000000000000000000096811115613c8557600081600c54613c159190615553565b90506000613c437f000000000000000000000000000000000000000000000000000000000000009683615065565b905082811115613c6e578186101580613c645750613c61838261504e565b86105b9350505050610f49565b818610158015613c64575085109250610f49915050565b6001915050610f49565b6001600160a01b0383166000908152601b602052604090205460ff1615613d115760405162461bcd60e51b815260206004820152603060248201527f436f6d6d756e69747920616e64204469726563743a204164647265737320686160448201526f1cc8185b1c9958591e481b5a5b9d195960821b6064820152608401610484565b6001600160a01b0383166000908152601b60205260409020805460ff19166001179055600e54613d4290849061418a565b6001600e6000828254613d559190615065565b90915550506040517f302c37e6ef624a63ae3d7d8bc4409b3d5c1ce5d6d4d25b067b57c242be4320ce90613d919085906001908690869061552b565b60405180910390a1505050565b816001600160a01b0316836001600160a01b031603613dff5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610484565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b613e7784848461358b565b613e83848484846141a4565b6114635760405162461bcd60e51b815260040161048490615567565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112349084906142a5565b606081600003613f185750506040805180820190915260018152600360fc1b602082015290565b8160005b8115613f425780613f2c816151f8565b9150613f3b9050600a83615297565b9150613f1c565b6000816001600160401b03811115613f5c57613f5c61477d565b6040519080825280601f01601f191660200182016040528015613f86576020820181803683370190505b5090505b841561358357613f9b60018361504e565b9150613fa8600a86615553565b613fb3906030615065565b60f81b818381518110613fc857613fc86151e2565b60200101906001600160f81b031916908160001a905350613fea600a86615297565b9450613f8a565b60065460ff16156112345760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610484565b600061404282611776565b905061405081600084613ff1565b61405b6000836133e0565b6001600160a01b038116600090815260036020526040812080546001929061408490849061504e565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600081815b8451811015614182576000858281518110614100576141006151e2565b6020026020010151905080831161414257604080516020810185905290810182905260600160405160208183030381529060405280519060200120925061416f565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b508061417a816151f8565b9150506140e3565b509392505050565b6112cf828260405180602001604052806000815250614377565b60006001600160a01b0384163b1561429a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906141e89033908990889088906004016155b9565b6020604051808303816000875af1925050508015614223575060408051601f3d908101601f19168201909252614220918101906155ec565b60015b614280573d808015614251576040519150601f19603f3d011682016040523d82523d6000602084013e614256565b606091505b5080516000036142785760405162461bcd60e51b815260040161048490615567565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050613583565b506001949350505050565b60006142fa826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143aa9092919063ffffffff16565b80519091501561123457808060200190518101906143189190615609565b6112345760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610484565b61438183836143b9565b61438e60008484846141a4565b6112345760405162461bcd60e51b815260040161048490615567565b60606135838484600085614507565b6001600160a01b03821661440f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610484565b6000818152600260205260409020546001600160a01b0316156144745760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610484565b61448060008383613ff1565b6001600160a01b03821660009081526003602052604081208054600192906144a9908490615065565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6060824710156145685760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610484565b843b6145b65760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610484565b600080866001600160a01b031685876040516145d29190615626565b60006040518083038185875af1925050503d806000811461460f576040519150601f19603f3d011682016040523d82523d6000602084013e614614565b606091505b509150915061462482828661462f565b979650505050505050565b6060831561463e5750816138e5565b82511561464e5782518084602001fd5b8160405162461bcd60e51b81526004016104849190614725565b6001600160a01b038116811461262a57600080fd5b60006020828403121561468f57600080fd5b81356138e581614668565b6001600160e01b03198116811461262a57600080fd5b6000602082840312156146c257600080fd5b81356138e58161469a565b60005b838110156146e85781810151838201526020016146d0565b838111156114635750506000910152565b600081518084526147118160208601602086016146cd565b601f01601f19169290920160200192915050565b6020815260006138e560208301846146f9565b60006020828403121561474a57600080fd5b5035919050565b6000806040838503121561476457600080fd5b823561476f81614668565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156147bb576147bb61477d565b604052919050565b60006001600160401b038211156147dc576147dc61477d565b50601f01601f191660200190565b60006147fd6147f8846147c3565b614793565b905082815283838301111561481157600080fd5b828260208301376000602084830101529392505050565b60006020828403121561483a57600080fd5b81356001600160401b0381111561485057600080fd5b8201601f8101841361486157600080fd5b613583848235602084016147ea565b60008083601f84011261488257600080fd5b5081356001600160401b0381111561489957600080fd5b6020830191508360208260051b850101111561165257600080fd5b6000806000604084860312156148c957600080fd5b83356001600160401b038111156148df57600080fd5b6148eb86828701614870565b909790965060209590950135949350505050565b6000806040838503121561491257600080fd5b823591506020808401356001600160401b038082111561493157600080fd5b818601915086601f83011261494557600080fd5b8135818111156149575761495761477d565b8060051b9150614968848301614793565b818152918301840191848101908984111561498257600080fd5b938501935b838510156149a057843582529385019390850190614987565b8096505050505050509250929050565b6000806000606084860312156149c557600080fd5b83356149d081614668565b925060208401356149e081614668565b929592945050506040919091013590565b60008060408385031215614a0457600080fd5b50508035926020909101359150565b600080600060408486031215614a2857600080fd5b8335614a3381614668565b925060208401356001600160401b03811115614a4e57600080fd5b614a5a86828701614870565b9497909650939450505050565b6001600160a01b038581168252841660208201528215156040820152608060608201819052600090614a9b908301846146f9565b9695505050505050565b60008060008060608587031215614abb57600080fd5b8435614ac681614668565b93506020850135925060408501356001600160401b03811115614ae857600080fd5b614af487828801614870565b95989497509550505050565b60008060208385031215614b1357600080fd5b82356001600160401b0380821115614b2a57600080fd5b818501915085601f830112614b3e57600080fd5b813581811115614b4d57600080fd5b866020828501011115614b5f57600080fd5b60209290920196919550909350505050565b600080600080600060808688031215614b8957600080fd5b8535945060208601356001600160401b03811115614ba657600080fd5b614bb288828901614870565b9699909850959660408101359660609091013595509350505050565b60008060008060008060808789031215614be757600080fd5b863595506020870135945060408701356001600160401b0380821115614c0c57600080fd5b614c188a838b01614870565b90965094506060890135915080821115614c3157600080fd5b50614c3e89828a01614870565b979a9699509497509295939492505050565b801515811461262a57600080fd5b60008060408385031215614c7157600080fd5b8235614c7c81614668565b91506020830135614c8c81614c50565b809150509250929050565b60008060008060608587031215614cad57600080fd5b8435935060208501356001600160401b03811115614cca57600080fd5b614cd687828801614870565b9598909750949560400135949350505050565b60008060008060808587031215614cff57600080fd5b8435614d0a81614668565b93506020850135614d1a81614668565b92506040850135915060608501356001600160401b03811115614d3c57600080fd5b8501601f81018713614d4d57600080fd5b614d5c878235602084016147ea565b91505092959194509250565b600060208284031215614d7a57600080fd5b81356001600160401b03811681146138e557600080fd5b600080600080600060808688031215614da957600080fd5b8535614db481614668565b94506020860135935060408601356001600160401b03811115614dd657600080fd5b614de288828901614870565b96999598509660600135949350505050565b600080600080600060808688031215614e0c57600080fd5b8535614e1781614668565b9450602086013593506040860135925060608601356001600160401b03811115614e4057600080fd5b614e4c88828901614870565b969995985093965092949392505050565b600060018060a01b038088168352861515602084015260a06040840152614e8760a08401876146f9565b606084019590955292909216608090910152509392505050565b600080600080600060608688031215614eb957600080fd5b8535945060208601356001600160401b0380821115614ed757600080fd5b614ee389838a01614870565b90965094506040880135915080821115614efc57600080fd5b50614e4c88828901614870565b60008060408385031215614f1c57600080fd5b8235614f2781614668565b91506020830135614c8c81614668565b60008060008060408587031215614f4d57600080fd5b84356001600160401b0380821115614f6457600080fd5b614f7088838901614870565b90965094506020870135915080821115614f8957600080fd5b50614af487828801614870565b60008060008060008060a08789031215614faf57600080fd5b8635614fba81614668565b95506020870135945060408701356001600160401b03811115614fdc57600080fd5b614fe889828a01614870565b979a9699509760608101359660809091013595509350505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008282101561506057615060615038565b500390565b6000821982111561507857615078615038565b500190565b600181811c9082168061509157607f821691505b6020821081036150b157634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561123457600081815260208120601f850160051c810160208610156150de5750805b601f850160051c820191505b818110156124b5578281556001016150ea565b81516001600160401b038111156151165761511661477d565b61512a81615124845461507d565b846150b7565b602080601f83116001811461515f57600084156151475750858301515b600019600386901b1c1916600185901b1785556124b5565b600085815260208120601f198616915b8281101561518e5788860151825594840194600190910190840161516f565b50858210156151ac5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6020808252600c908201526b131a5cdd1cc81b1bd8dad95960a21b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60006001820161520a5761520a615038565b5060010190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b600081600019048311821515161561527c5761527c615038565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826152a6576152a6615281565b500490565b6001600160401b038311156152c2576152c261477d565b6152d6836152d0835461507d565b836150b7565b6000601f84116001811461530a57600085156152f25750838201355b600019600387901b1c1916600186901b178355615364565b600083815260209020601f19861690835b8281101561533b578685013582556020948501946001909201910161531b565b50868210156153585760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60208082526013908201527213585e081cdd5c1c1b1e48195e18d959591959606a1b604082015260600190565b60208082526017908201527f496e73756666696369656e742045544820706173736564000000000000000000604082015260600190565b6000602082840312156153e157600080fd5b81516001600160401b038111156153f757600080fd5b8201601f8101841361540857600080fd5b80516154166147f8826147c3565b81815285602083850101111561542b57600080fd5b61543c8260208301602086016146cd565b95945050505050565b60008084546154538161507d565b6001828116801561546b5760018114615480576154af565b60ff19841687528215158302870194506154af565b8860005260208060002060005b858110156154a65781548a82015290840190820161548d565b50505082870194505b5050505083516154c38183602088016146cd565b64173539b7b760d91b9101908152600501949350505050565b6000602082840312156154ee57600080fd5b5051919050565b81835260006001600160fb1b0383111561550e57600080fd5b8260051b8083602087013760009401602001938452509192915050565b60018060a01b0385168152836020820152606060408201526000614a9b6060830184866154f5565b60008261556257615562615281565b500690565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614a9b908301846146f9565b6000602082840312156155fe57600080fd5b81516138e58161469a565b60006020828403121561561b57600080fd5b81516138e581614c50565b600082516156388184602087016146cd565b919091019291505056fe4469726563743a20416464726573732068617320616c7265616479206d696e74656454726561737572793a2052657175657374696e67206d6f7265207468616e2072656d61696e696e6720616c6c6f636174696f6e436c61696d3a20416464726573732068617320616c7265616479206d696e746564436f6d706c6574696f6e3a2052657175657374696e67206d6f7265207468616e2072656d61696e696e6720616c6c6f636174696f6e436f6d6d756e6974793a20416464726573732068617320616c7265616479206d696e746564a2646970667358221220f75bdcb4c15e2447783574fbd1d944ef6b4982840c677f80d18940ad62b3edcf64736f6c634300080f0033
Verified Source Code Full Match
Compiler: v0.8.15+commit.e14f2714
EVM: london
Optimization: Yes (200 runs)
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
ERC721.sol 424 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
VRFConsumerBaseV2.sol 133 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
* @dev PURPOSE
*
* @dev Reggie the Random Oracle (not his real job) wants to provide randomness
* @dev to Vera the verifier in such a way that Vera can be sure he's not
* @dev making his output up to suit himself. Reggie provides Vera a public key
* @dev to which he knows the secret key. Each time Vera provides a seed to
* @dev Reggie, he gives back a value which is computed completely
* @dev deterministically from the seed and the secret key.
*
* @dev Reggie provides a proof by which Vera can verify that the output was
* @dev correctly computed once Reggie tells it to her, but without that proof,
* @dev the output is indistinguishable to her from a uniform random sample
* @dev from the output space.
*
* @dev The purpose of this contract is to make it easy for unrelated contracts
* @dev to talk to Vera the verifier about the work Reggie is doing, to provide
* @dev simple access to a verifiable source of randomness. It ensures 2 things:
* @dev 1. The fulfillment came from the VRFCoordinator
* @dev 2. The consumer contract implements fulfillRandomWords.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFConsumerBase, and can
* @dev initialize VRFConsumerBase's attributes in their constructor as
* @dev shown:
*
* @dev contract VRFConsumer {
* @dev constructor(<other arguments>, address _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator) public {
* @dev <initialization with other arguments goes here>
* @dev }
* @dev }
*
* @dev The oracle will have given you an ID for the VRF keypair they have
* @dev committed to (let's call it keyHash). Create subscription, fund it
* @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface
* @dev subscription management functions).
* @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
* @dev callbackGasLimit, numWords),
* @dev see (VRFCoordinatorInterface for a description of the arguments).
*
* @dev Once the VRFCoordinator has received and validated the oracle's response
* @dev to your request, it will call your contract's fulfillRandomWords method.
*
* @dev The randomness argument to fulfillRandomWords is a set of random words
* @dev generated from your requestId and the blockHash of the request.
*
* @dev If your contract could have concurrent requests open, you can use the
* @dev requestId returned from requestRandomWords to track which response is associated
* @dev with which randomness request.
* @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind,
* @dev if your contract could have multiple requests in flight simultaneously.
*
* @dev Colliding `requestId`s are cryptographically impossible as long as seeds
* @dev differ.
*
* *****************************************************************************
* @dev SECURITY CONSIDERATIONS
*
* @dev A method with the ability to call your fulfillRandomness method directly
* @dev could spoof a VRF response with any random value, so it's critical that
* @dev it cannot be directly called by anything other than this base contract
* @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
*
* @dev For your users to trust that your contract's random behavior is free
* @dev from malicious interference, it's best if you can write it so that all
* @dev behaviors implied by a VRF response are executed *during* your
* @dev fulfillRandomness method. If your contract must store the response (or
* @dev anything derived from it) and use it later, you must ensure that any
* @dev user-significant behavior which depends on that stored value cannot be
* @dev manipulated by a subsequent VRF request.
*
* @dev Similarly, both miners and the VRF oracle itself have some influence
* @dev over the order in which VRF responses appear on the blockchain, so if
* @dev your contract could have multiple VRF requests in flight simultaneously,
* @dev you must ensure that the order in which the VRF responses arrive cannot
* @dev be used to manipulate your contract's user-significant behavior.
*
* @dev Since the block hash of the block which contains the requestRandomness
* @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
* @dev miner could, in principle, fork the blockchain to evict the block
* @dev containing the request, forcing the request to be included in a
* @dev different block with a different hash, and therefore a different input
* @dev to the VRF. However, such an attack would incur a substantial economic
* @dev cost. This cost scales with the number of blocks the VRF oracle waits
* @dev until it calls responds to a request. It is for this reason that
* @dev that you can signal to an oracle you'd like them to wait longer before
* @dev responding to the request (however this is not enforced in the contract
* @dev and so remains effective only in the case of unmodified oracle software).
*/
abstract contract VRFConsumerBaseV2 {
error OnlyCoordinatorCanFulfill(address have, address want);
address private immutable vrfCoordinator;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
*/
constructor(address _vrfCoordinator) {
vrfCoordinator = _vrfCoordinator;
}
/**
* @notice fulfillRandomness handles the VRF response. Your contract must
* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
* @notice principles to keep in mind when implementing your fulfillRandomness
* @notice method.
*
* @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
* @dev signature, and will call it once it has verified the proof
* @dev associated with the randomness. (It is triggered via a call to
* @dev rawFulfillRandomness, below.)
*
* @param requestId The Id initially returned by requestRandomness
* @param randomWords the VRF output expanded to the requested number of words
*/
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;
// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
// the origin of the call
function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
if (msg.sender != vrfCoordinator) {
revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
}
fulfillRandomWords(requestId, randomWords);
}
}
IWebaverseLand.sol 7 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
interface IWebaverseLand {
// Function to call to return the tokenURI for a passed token Id
function uriForToken(uint256 tokenId_) external view returns (string memory);
}
Ownable.sol 76 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
VRFCoordinatorV2Interface.sol 116 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface VRFCoordinatorV2Interface {
/**
* @notice Get configuration relevant for making requests
* @return minimumRequestConfirmations global min for request confirmations
* @return maxGasLimit global max for request gas limit
* @return s_provingKeyHashes list of registered key hashes
*/
function getRequestConfig()
external
view
returns (
uint16,
uint32,
bytes32[] memory
);
/**
* @notice Request a set of random words.
* @param keyHash - Corresponds to a particular oracle job which uses
* that key for generating the VRF proof. Different keyHash's have different gas price
* ceilings, so you can select a specific one to bound your maximum per request cost.
* @param subId - The ID of the VRF subscription. Must be funded
* with the minimum subscription balance required for the selected keyHash.
* @param minimumRequestConfirmations - How many blocks you'd like the
* oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
* for why you may want to request more. The acceptable range is
* [minimumRequestBlockConfirmations, 200].
* @param callbackGasLimit - How much gas you'd like to receive in your
* fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
* may be slightly less than this amount because of gas used calling the function
* (argument decoding etc.), so you may need to request slightly more than you expect
* to have inside fulfillRandomWords. The acceptable range is
* [0, maxGasLimit]
* @param numWords - The number of uint256 random values you'd like to receive
* in your fulfillRandomWords callback. Note these numbers are expanded in a
* secure way by the VRFCoordinator from a single random value supplied by the oracle.
* @return requestId - A unique identifier of the request. Can be used to match
* a request to a response in fulfillRandomWords.
*/
function requestRandomWords(
bytes32 keyHash,
uint64 subId,
uint16 minimumRequestConfirmations,
uint32 callbackGasLimit,
uint32 numWords
) external returns (uint256 requestId);
/**
* @notice Create a VRF subscription.
* @return subId - A unique subscription id.
* @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
* @dev Note to fund the subscription, use transferAndCall. For example
* @dev LINKTOKEN.transferAndCall(
* @dev address(COORDINATOR),
* @dev amount,
* @dev abi.encode(subId));
*/
function createSubscription() external returns (uint64 subId);
/**
* @notice Get a VRF subscription.
* @param subId - ID of the subscription
* @return balance - LINK balance of the subscription in juels.
* @return reqCount - number of requests for this subscription, determines fee tier.
* @return owner - owner of the subscription.
* @return consumers - list of consumer address which are able to use this subscription.
*/
function getSubscription(uint64 subId)
external
view
returns (
uint96 balance,
uint64 reqCount,
address owner,
address[] memory consumers
);
/**
* @notice Request subscription owner transfer.
* @param subId - ID of the subscription
* @param newOwner - proposed new owner of the subscription
*/
function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;
/**
* @notice Request subscription owner transfer.
* @param subId - ID of the subscription
* @dev will revert if original owner of subId has
* not requested that msg.sender become the new owner.
*/
function acceptSubscriptionOwnerTransfer(uint64 subId) external;
/**
* @notice Add a consumer to a VRF subscription.
* @param subId - ID of the subscription
* @param consumer - New consumer which can use the subscription
*/
function addConsumer(uint64 subId, address consumer) external;
/**
* @notice Remove a consumer from a VRF subscription.
* @param subId - ID of the subscription
* @param consumer - Consumer to remove from the subscription
*/
function removeConsumer(uint64 subId, address consumer) external;
/**
* @notice Cancel a subscription
* @param subId - ID of the subscription
* @param to - Where to send the remaining LINK to
*/
function cancelSubscription(uint64 subId, address to) external;
}
MerkleProof.sol 52 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Trees proofs.
*
* The proofs can be generated using the JavaScript library
* https://github.com/miguelmota/merkletreejs[merkletreejs].
* Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
*
* See `test/utils/cryptography/MerkleProof.test.js` for some examples.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*
* _Available since v4.4._
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
return computedHash;
}
}
IERC721Receiver.sol 27 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
WebaverseGenesisPass.sol 1201 lines
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "./IWebaverseLand.sol";
/**
*
* @dev Inheritance details:
* ERC721 ERC721 token standard, imported from openzeppelin
* Pausable Allows functions to be Paused, note that this contract includes the metadrop
* time-limited pause, where the contract can only be paused for a defined time period.
* Imported from openzeppelin.
* Ownable Allow priviledged access to certain functions. Imported from openzeppelin.
* ERC721Burnable Helper library for convenient burning of ERC721s. Imported from openzeppelin.
* VRFConsumerBaseV2 Chainlink RNG contract. Imported from chainlink.
*
*/
contract WebaverseGenesisPass is
ERC721,
Pausable,
Ownable,
ERC721Burnable,
VRFConsumerBaseV2
{
using SafeERC20 for IERC20;
using Strings for uint256;
/**
* @dev Chainlink config.
*/
VRFCoordinatorV2Interface vrfCoordinator;
uint64 vrfSubscriptionId;
// The gas lane to use, which specifies the maximum gas price to bump to.
// For a list of available gas lanes on each network,
// see https://docs.chain.link/docs/vrf-contracts/#configurations
bytes32 vrfKeyHash;
// Depends on the number of requested values that you want sent to the
// fulfillRandomWords() function. Storing each word costs about 20,000 gas,
// so 100,000 is a safe default for this example contract. Test and adjust
// this limit based on the network that you select, the size of the request,
// and the processing of the callback request in the fulfillRandomWords()
// function.
uint32 vrfCallbackGasLimit = 150000;
// The default is 3, but you can set this higher.
uint16 vrfRequestConfirmations = 3;
// Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
uint32 vrfNumWords = 1;
uint256 public immutable maxSupply;
uint256 public immutable numberOfCommunities;
uint256 public immutable mintPrice;
uint256 public immutable maxCommunityWhitelistLength;
uint256 public immutable whitelistMintStart;
uint256 public immutable whitelistMintEnd;
address payable public immutable beneficiaryAddress;
string private _tokenBaseURI;
string public placeholderTokenURI;
uint256 public communityRandomness;
uint256 private _royaltyPercentageBasisPoints;
uint256 public tokenIdCounter;
uint256 public burnCounter;
// Slot size (32 + 160 + 8 + 8 + 8 = 216)
// ERC-2981: NFT Royalty Standard
bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
address private _royaltyReceipientAddress;
bool public tokenBaseURILocked;
bool public listsLocked;
bool public webaverseLandAddressLocked;
bool public placeholderTokenURILocked;
// Claim whitelist merkle root - for auction
// hash(quantity, address)
bytes32 public claimWhitelistMerkleRoot;
mapping(address => bool) private _claimHasMinted;
// Treasury whitelist merkle root - for metadrop & webaverse treasury
// hash(quantity, address)
bytes32 public treasuryWhitelistMerkleRoot;
mapping(address => uint256) private _treasuryAllocationMinted;
// Direct whitelist merkle root
// hash(position, address)
bytes32 public directWhitelistMerkleRoot;
// Community whitelist merkle root
// hash(community, position, address)
bytes32 public communityWhitelistMerkleRoot;
// Community ID => Community whitelist merkle length
mapping(uint256 => uint256) public communityWhitelistLengths;
// Completion whitelist merkle root
// hash(quantity, address, unitPrice)
bytes32 public completionWhitelistMerkleRoot;
mapping(address => uint256) private _completionAllocationMinted;
uint256 public pauseCutoffDays;
// Single bool for first stage mint (direct and community) - each
// address can only mint once, regardless of multiple eligibility:
mapping(address => bool) private _firstStageAddressHasMinted;
// Webaverse Land contract address:
address public webaverseLandAddress;
/**
*
* @dev constructor: Must be passed following addresses:
* * chainlink VRF address and Link token address
*
*/
constructor(
// configIntegers array must contain the following:
// [0]: numberOfCommunities (e.g. 7)
// [1]: maxCommunityWhitlistLength (how many slots are open per community, beyond which we 'lottery' using a randon start position)
// [2]: whitelistMintStart (timestamp of when the stage 1 mint will start)
// [3]: pauseCutoffDays (when the ability to pause this contract expires)
uint256[] memory configIntegers_,
uint256 maxSupply_,
uint256 mintPrice_,
address royaltyReceipientAddress_,
uint256 royaltyPercentageBasisPoints_,
address vrfCoordinator_,
bytes32 vrfKeyHash_,
address payable beneficiaryAddress_
)
ERC721("Webaverse Genesis Pass", "WEBA")
VRFConsumerBaseV2(vrfCoordinator_)
{
numberOfCommunities = configIntegers_[0];
maxCommunityWhitelistLength = configIntegers_[1];
whitelistMintStart = configIntegers_[2];
pauseCutoffDays = configIntegers_[3];
whitelistMintEnd = whitelistMintStart + 2 days;
maxSupply = maxSupply_;
mintPrice = mintPrice_;
_royaltyReceipientAddress = royaltyReceipientAddress_;
_royaltyPercentageBasisPoints = royaltyPercentageBasisPoints_;
vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinator_);
vrfKeyHash = vrfKeyHash_;
beneficiaryAddress = beneficiaryAddress_;
}
/**
*
* @dev WebaverseVotes: Emit the votes cast with this mint to be tallied off-chain.
*
*/
event WebaverseVotes(address voter, uint256 quantityMinted, uint256[] votes);
/**
*
* @dev Only allow when stage 1 whitelist minting is open:
*
*/
modifier whenStage1MintingOpen() {
require(stage1MintingOpen(), "Stage 1 mint closed");
require(communityRandomness != 0, "Community randomness not set");
_;
}
/**
*
* @dev whenListsUnlocked: restrict access to when the lists are unlocked.
* This allows the owner to effectively end new minting, with eligibility
* fixed to the details on the merkle roots (and associated lists) already
* saved in storage
*
*/
modifier whenListsUnlocked() {
require(!listsLocked, "Lists locked");
_;
}
/**
*
* @dev whenLandAddressUnlocked: the webaverse land address cannot be
* updated after it has been locked
*
*/
modifier whenLandAddressUnlocked() {
require(!webaverseLandAddressLocked, "Land address locked");
_;
}
/**
*
* @dev whenPlaceholderURIUnlocked: the placeholder URI cannot be
* updated after it has been locked
*
*/
modifier whenPlaceholderURIUnlocked() {
require(!placeholderTokenURILocked, "Place holder URI locked");
_;
}
/**
*
* @dev whenSupplyRemaining: Supply is controlled by lists and cannot be exceeded, but as
* an explicity and clear control we check here that the mint operation requested will not
* exceed the max supply.
*
*/
modifier whenSupplyRemaining(uint256 quantity_) {
require((tokenIdCounter + quantity_) <= maxSupply, "Max supply exceeded");
_;
}
/**
*
* @dev stage1MintingOpen: View of whether stage 1 mint is open
*
*/
function stage1MintingOpen() public view returns (bool) {
return
block.timestamp > (whitelistMintStart - 1) &&
block.timestamp < (whitelistMintEnd + 1);
}
/**
*
* @dev isStage1MintingEnded: View of whether stage 1 mint is ended
*
*/
function stage1MintingEnded() public view returns (bool) {
return block.timestamp > whitelistMintEnd;
}
/**
* totalSupply is the number of tokens minted (value tokenIdCounter, as this is 0
* indexed by always set to the next ID it will issue) minus burned
*/
function totalSupply() public view returns (uint256) {
return tokenIdCounter - burnCounter;
}
/**
*
* @dev getRandomNumber: Requests randomness.
*
*/
function getRandomNumber() public onlyOwner returns (uint256) {
require(communityWhitelistMerkleRoot != 0, "Community list not set");
require(communityRandomness == 0, "Randomness set");
return
vrfCoordinator.requestRandomWords(
vrfKeyHash,
vrfSubscriptionId,
vrfRequestConfirmations,
vrfCallbackGasLimit,
vrfNumWords
);
}
/**
*
* @dev fulfillRandomWords: Callback function used by VRF Coordinator.
* This function is used to generate random values used in community & claim minting
*
*/
function fulfillRandomWords(uint256, uint256[] memory randomWords_)
internal
override
{
require(communityRandomness == 0, "Randomness set");
communityRandomness = randomWords_[0];
}
/**
*
* @dev setVRFSubscriptionId: Set the chainlink subscription id.
*
*/
function setVRFSubscriptionId(uint64 vrfSubscriptionId_) external onlyOwner {
vrfSubscriptionId = vrfSubscriptionId_;
}
/**
*
* @dev withdrawContractBalance: A withdraw function to allow ETH balance to be withdrawn to the beneficiary address
* set in the constructor
*
*/
function withdrawContractBalance() external onlyOwner {
(bool success, ) = beneficiaryAddress.call{value: address(this).balance}(
""
);
require(success, "Transfer failed");
}
/**
*
* @dev receive: Handles receiving ether to the contract. Reject all direct payments to the contract except from beneficiary and owner.
* set in the constructor
*
*/
receive() external payable {
require(msg.value > 0, "No ETH");
require(
msg.sender == beneficiaryAddress || msg.sender == owner(),
"Only owner or beneficiary"
);
}
/**
*
* @dev transferERC20Token: A withdraw function to avoid locking ERC20 tokens in the contract forever.
* Tokens can only be withdrawn by the owner, to the owner.
*
*/
function transferERC20Token(IERC20 token, uint256 amount) public onlyOwner {
token.safeTransfer(owner(), amount);
}
/**
*
* @dev pause: Allow owner to pause.
*
*/
function pause() public onlyOwner {
require(
whitelistMintStart == 0 ||
block.timestamp < (whitelistMintStart + pauseCutoffDays * 1 days),
"Pause cutoff passed"
);
_pause();
}
/**
*
* @dev unpause: Allow owner to unpause.
*
*/
function unpause() public onlyOwner {
_unpause();
}
/**
*
* @dev lockLists: Prevent any further changes to list merkle roots.
*
*/
function lockLists() public onlyOwner {
listsLocked = true;
}
/**
*
* @dev lockLandAddress: Prevent any further changes to the webaverse land contract address.
*
*/
function lockLandAddress() public onlyOwner {
webaverseLandAddressLocked = true;
}
/**
*
* @dev setLandAddress: Set the root for the auction claims.
*
*/
function setLandAddress(address webaverseLandAddress_)
external
onlyOwner
whenLandAddressUnlocked
{
webaverseLandAddress = webaverseLandAddress_;
}
/**
*
* @dev lockPlaceholderTokenURI: Prevent any further changes to the placeholder URI.
*
*/
function lockPlaceholderTokenURI() public onlyOwner {
placeholderTokenURILocked = true;
}
/**
*
* @dev setPlaceholderTokenURI: Set the string for the placeholder
* token URI.
*
*/
function setPlaceholderTokenURI(string memory placeholderTokenURI_)
external
onlyOwner
whenPlaceholderURIUnlocked
{
placeholderTokenURI = placeholderTokenURI_;
}
/**
*
* @dev setDirectWhitelist: Set the initial data for the direct list mint.
*
*/
function setDirectWhitelist(bytes32 directWhitelistMerkleRoot_)
external
whenListsUnlocked
onlyOwner
{
directWhitelistMerkleRoot = directWhitelistMerkleRoot_;
}
/**
*
* @dev setCommunityWhitelist: Set the initial data for the community mint.
*
*/
function setCommunityWhitelist(
uint256[] calldata communityWhitelistLengths_,
bytes32 communityWhitelistMerkleRoot_
) external whenListsUnlocked onlyOwner {
require(
communityWhitelistLengths_.length == numberOfCommunities,
"Community length doesnt match"
);
communityWhitelistMerkleRoot = communityWhitelistMerkleRoot_;
for (
uint256 communityId = 0;
communityId < numberOfCommunities;
communityId++
) {
communityWhitelistLengths[communityId] = communityWhitelistLengths_[
communityId
];
}
}
/**
*
* @dev setClaimWhitelistMerkleRoot: Set the root for the auction claims.
*
*/
function setClaimWhitelistMerkleRoot(bytes32 claimWhitelistMerkleRoot_)
external
whenListsUnlocked
onlyOwner
{
claimWhitelistMerkleRoot = claimWhitelistMerkleRoot_;
}
/**
*
* @dev setTreasuryWhitelistMerkleRoot: Set the root for the treasury claims (metadrop + webaverse allocations).
*
*/
function setTreasuryWhitelistMerkleRoot(bytes32 treasuryWhitelistMerkleRoot_)
external
whenListsUnlocked
onlyOwner
{
treasuryWhitelistMerkleRoot = treasuryWhitelistMerkleRoot_;
}
/**
*
* @dev setCompletionWhitelistMerkleRoot: Set the root for completion mints.
*
*/
function setCompletionWhitelistMerkleRoot(
bytes32 completionWhitelistMerkleRoot_
) external whenListsUnlocked onlyOwner {
completionWhitelistMerkleRoot = completionWhitelistMerkleRoot_;
}
/**
*
* @dev _getCommunityHash: Get hash of information for the community mint.
*
*/
function _getCommunityHash(
uint256 community_,
uint256 position_,
address minter_
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(community_, position_, minter_));
}
/**
*
* @dev _getDirectHash: Get hash of information for mints for direct list.
*
*/
function _getDirectHash(address minter_) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(minter_));
}
/**
*
* @dev _getClaimAndTreasuryHash: Get hash of information for mints from the auction (claims).
* Also the same hash format as the treasury whitelist, used for treasuryWhitelistMerkleRoot too
*
*/
function _getClaimAndTreasuryHash(uint256 quantity_, address minter_)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(quantity_, minter_));
}
/**
*
* @dev _getCompletionHash: Get hash of information for mints from the auction (claims).
* Also the same hash format as the treasury whitelist, used for treasuryWhitelistMerkleRoot too
*
*/
function _getCompletionHash(
uint256 quantity_,
address minter_,
uint256 unitPrice_
) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(quantity_, minter_, unitPrice_));
}
/**
*
* @dev isValidPosition: Check is this is a valid position for this community allowlist. There are
* 1,000 positions per community. If more than 1,000 have registered a random start position in the
* allowlist is used to determine eligibility.
*
*/
function isValidPosition(uint256 position_, uint256 community_)
internal
view
returns (bool)
{
uint256 communityWhitelistLength = communityWhitelistLengths[community_];
require(communityWhitelistLength > 0, "Length not set");
if (communityWhitelistLength > maxCommunityWhitelistLength) {
// Find the random starting point somewhere in the whitelist length array
uint256 startPoint = communityRandomness % communityWhitelistLength;
uint256 endPoint = startPoint + maxCommunityWhitelistLength;
// If the valid range exceeds the length of the whitelist, it must roll over
if (endPoint > communityWhitelistLength) {
return
position_ >= startPoint ||
position_ < endPoint - communityWhitelistLength;
} else {
return position_ >= startPoint && position_ < endPoint;
}
} else {
return true;
}
}
/**
*
* @dev _checkTheVote: check the count of votes = the quantity minted:
*
*/
function _checkTheVote(uint256[] memory votesToCount_, uint256 quantity_)
internal
view
{
// (1) Check that we have been passed the right number of community votes in the array:
require(
votesToCount_.length == numberOfCommunities,
"Vote array does not match community count"
);
// (2) Check that the total votes matches the mint quantity:
uint256 totalVotes;
for (uint256 i = 0; i < votesToCount_.length; i++) {
totalVotes += votesToCount_[i];
}
require(totalVotes == quantity_, "Votes do not match minting quantity");
}
/**
*
* @dev communityMint: Minting of community allocations from the allowlist.
*
*/
function communityMint(
uint256 community_,
uint256 position_,
bytes32[] calldata proof_,
uint256[] calldata votes_
) external payable whenStage1MintingOpen whenSupplyRemaining(1) {
require(msg.value == mintPrice, "Insufficient ETH passed");
require(communityWhitelistMerkleRoot != 0, "Community merkle root not set");
// Check the total votes passed equals the minted quantity:
_checkTheVote(votes_, 1);
bytes32 leaf = _getCommunityHash(community_, position_, msg.sender);
require(
MerkleProof.verify(proof_, communityWhitelistMerkleRoot, leaf),
"Community mint proof invalid"
);
require(
isValidPosition(position_, community_),
"This position has missed out"
);
_performDirectAndCommunityMint(msg.sender, votes_);
}
/**
*
* @dev directMint: Mint allocations from the webaverse direct allowlist
*
*/
function directMint(bytes32[] calldata proof_, uint256[] calldata votes_)
external
payable
whenStage1MintingOpen
whenSupplyRemaining(1)
{
require(msg.value == mintPrice, "Insufficient ETH passed");
require(directWhitelistMerkleRoot != 0, "Direct merkle root not set");
// Check the total votes passed equals the minted quantity:
_checkTheVote(votes_, 1);
bytes32 leaf = _getDirectHash(msg.sender);
require(
MerkleProof.verify(proof_, directWhitelistMerkleRoot, leaf),
"Direct mint proof invalid"
);
_performDirectAndCommunityMint(msg.sender, votes_);
}
/**
*
* @dev claimMint: Whitelist proof is generated from quantity and address
*
*/
function claimMint(
uint256 quantityToMint_,
bytes32[] calldata proof_,
uint256[] calldata votes_
) public whenSupplyRemaining(quantityToMint_) {
require(claimWhitelistMerkleRoot != 0, "Mint merkle root not set");
// Check the total votes passed equals the minted quantity:
_checkTheVote(votes_, quantityToMint_);
bytes32 leaf = _getClaimAndTreasuryHash(quantityToMint_, msg.sender);
require(
MerkleProof.verify(proof_, claimWhitelistMerkleRoot, leaf),
"Claim mint proof invalid"
);
require(!_claimHasMinted[msg.sender], "Claim: Address has already minted");
_claimHasMinted[msg.sender] = true;
_batchMint(msg.sender, quantityToMint_);
emit WebaverseVotes(msg.sender, quantityToMint_, votes_);
}
/**
*
* @dev treasuryMint: Mint function for metadrop & webaverse treasury + other parties
*
*/
function treasuryMint(
uint256 quantityEligible_,
bytes32[] calldata proof_,
uint256 quantityToMint_
) public whenSupplyRemaining(quantityToMint_) {
require(treasuryWhitelistMerkleRoot != 0, "Mint merkle root not set");
bytes32 leaf = _getClaimAndTreasuryHash(quantityEligible_, msg.sender);
require(
MerkleProof.verify(proof_, treasuryWhitelistMerkleRoot, leaf),
"Treasury: mint proof invalid"
);
require(
(_treasuryAllocationMinted[msg.sender] + quantityToMint_) <=
quantityEligible_,
"Treasury: Requesting more than remaining allocation"
);
_treasuryAllocationMinted[msg.sender] += quantityToMint_;
_batchMint(msg.sender, quantityToMint_);
}
/**
*
* @dev completionMint
*
*/
function completionMint(
uint256 quantityEligible_,
bytes32[] calldata proof_,
uint256 quantityToMint_,
uint256 unitPrice_
) public payable whenSupplyRemaining(quantityToMint_) {
require(
msg.value == (quantityToMint_ * unitPrice_),
"Insufficient ETH passed"
);
require(
completionWhitelistMerkleRoot != 0,
"Completion merkle root not set"
);
bytes32 leaf = _getCompletionHash(
quantityEligible_,
msg.sender,
unitPrice_
);
require(
MerkleProof.verify(proof_, completionWhitelistMerkleRoot, leaf),
"Completion: mint proof invalid"
);
require(
(_completionAllocationMinted[msg.sender] + quantityToMint_) <=
quantityEligible_,
"Completion: Requesting more than remaining allocation"
);
_completionAllocationMinted[msg.sender] += quantityToMint_;
_batchMint(msg.sender, quantityToMint_);
}
/**
*
* @dev _performDirectAndCommunityMint: Unified processing for direct and community mint
*
*/
function _performDirectAndCommunityMint(
address minter_,
uint256[] calldata votes_
) internal {
require(
!_firstStageAddressHasMinted[minter_],
"Community and Direct: Address has already minted"
);
_firstStageAddressHasMinted[minter_] = true;
_safeMint(minter_, tokenIdCounter);
tokenIdCounter += 1;
emit WebaverseVotes(minter_, 1, votes_);
}
/**
*
* @dev _batchMint: Unified processing for treasury, claim and completion mint
*
*/
function _batchMint(address minter_, uint256 quantity_) internal {
uint256 tempTokenIdCounter = tokenIdCounter;
for (uint256 i = 0; i < quantity_; i++) {
_safeMint(minter_, tempTokenIdCounter);
tempTokenIdCounter += 1;
}
tokenIdCounter = tempTokenIdCounter;
}
/**
*
* @dev setRoyaltyPercentageBasisPoints: allow the owner to set the base royalty percentage.
*
*/
function setRoyaltyPercentageBasisPoints(
uint256 royaltyPercentageBasisPoints_
) external onlyOwner {
_royaltyPercentageBasisPoints = royaltyPercentageBasisPoints_;
}
/**
*
* @dev setRoyaltyReceipientAddress: Allow the owner to set the royalty recipient.
*
*/
function setRoyaltyReceipientAddress(
address payable royaltyReceipientAddress_
) external onlyOwner {
_royaltyReceipientAddress = royaltyReceipientAddress_;
}
/**
*
* @dev setTokenBaseURI: Allow the owner to set the base token URI
*
*/
function setTokenBaseURI(string calldata tokenBaseURI_) external onlyOwner {
require(!tokenBaseURILocked, "Token base URI is locked");
_tokenBaseURI = tokenBaseURI_;
}
/**
*
* @dev lockTokenBaseURI: allow the owner to lock the base token URI, after which the URI cannot be altered.
*
*/
function lockTokenBaseURI() external onlyOwner {
require(!tokenBaseURILocked, "Token base URI is locked");
tokenBaseURILocked = true;
}
/**
*
* @dev royaltyInfo: Returns recipent address and royalty.
*
*/
function royaltyInfo(uint256, uint256 salePrice_)
external
view
returns (address receiver, uint256 royaltyAmount)
{
uint256 royalty = (salePrice_ * _royaltyPercentageBasisPoints) / 10000;
return (_royaltyReceipientAddress, royalty);
}
/**
*
* @dev _baseURI: returns the URI
*
*/
function _baseURI() internal view override returns (string memory) {
return _tokenBaseURI;
}
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
// If there is a land contract address set, use that address to retrieve the tokenURI:
if (webaverseLandAddress != address(0)) {
// Call the contract to return the token URI for this token ID:
return IWebaverseLand(webaverseLandAddress).uriForToken(tokenId);
// See if we have a token base URI set:
} else if (bytes(_tokenBaseURI).length != 0) {
// Return tokenBaseURI appended with the tokenId number:
return
string(abi.encodePacked(_tokenBaseURI, tokenId.toString(), ".json"));
// If neither of the above, use the placeholder URI
} else {
// The placeholder URI is the same for all tokenIds:
return placeholderTokenURI;
}
}
/**
*
* @dev _beforeTokenTransfer: function called before tokens are transfered.
*
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal override(ERC721) whenNotPaused {
super._beforeTokenTransfer(from, to, tokenId);
}
/**
*
* @dev supportsInterface: ERC2981 interface support.
*
*/
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721)
returns (bool)
{
return
interfaceId == _INTERFACE_ID_ERC2981 ||
super.supportsInterface(interfaceId);
}
/**
* ============================
* Web app eligibility getters:
* ============================
*/
/**
*
* @dev eligibleForCommunityMint: Eligibility check for the COMMUNITY mint. This can be called from front-end (for example to control
* screen components that indicate if the connected address is eligible).
*
* Function flow is as follows:
* (1) Check that the position, community and address are in the allowlist.
* (2) Check if this leaf has already minted. If so, exit with false eligibility and reason "Sender has already minted for this community"
* (3) Check if this leaf is in a valid position in the allowlist. If not, exit with false eligilibity and reason "This position has missed out"
* (4) All checks passed, return elibility = true, the delivery address and valid leaf.
*
*/
function eligibleForCommunityMint(
address addressToCheck_,
uint256 position_,
uint256 community_,
bytes32[] calldata proof_
)
external
view
returns (
address,
bool eligible,
string memory reason,
bytes32 leaf,
address
)
{
leaf = _getCommunityHash(community_, position_, addressToCheck_);
if (
MerkleProof.verify(proof_, communityWhitelistMerkleRoot, leaf) == false
) {
return (
addressToCheck_,
false,
"Community mint proof invalid",
leaf,
addressToCheck_
);
}
if (_firstStageAddressHasMinted[addressToCheck_]) {
return (
addressToCheck_,
false,
"Community: Address has already minted",
leaf,
addressToCheck_
);
}
if (!isValidPosition(position_, community_)) {
return (
addressToCheck_,
false,
"This position has missed out",
leaf,
addressToCheck_
);
}
return (addressToCheck_, true, "", leaf, addressToCheck_);
}
/**
*
* @dev eligibleForDirectMint: Eligibility check for the DIRECT mint. This can be called from front-end (for example to control
* screen components that indicate if the connected address is eligible).
*
* Function flow is as follows:
* (1) Check that the position and address are in the allowlist.
* (2) Check if this minter address has already minted. If so, exit with false eligibility and reason "Address has already minted"
* (3) All checks passed, return elibility = true, the delivery address and valid minter adress.
*
*/
function eligibleForDirectMint(
address addressToCheck_,
bytes32[] calldata proof_
)
external
view
returns (
address,
address,
bool eligible,
string memory reason
)
{
bytes32 leaf = _getDirectHash(addressToCheck_);
if (MerkleProof.verify(proof_, directWhitelistMerkleRoot, leaf) == false) {
return (
addressToCheck_,
addressToCheck_,
false,
"Direct mint proof invalid"
);
}
if (_firstStageAddressHasMinted[addressToCheck_]) {
return (
addressToCheck_,
addressToCheck_,
false,
"Direct: Address has already minted"
);
}
return (addressToCheck_, addressToCheck_, true, "");
}
/**
*
* @dev eligibleForClaimMint: Eligibility check for the CLAIM mint. This can be called from front-end (for example to control
* screen components that indicate if the connected address is eligible).
*
* Function flow is as follows:
* (1) Check that the position and address are in the allowlist.
* (2) Check if this minter address has already minted. If so, exit with false eligibility and reason "Address has already minted"
* (3) All checks passed, return elibility = true, the delivery address and valid minter adress.
*
*/
function eligibleForClaimMint(
address addressToCheck_,
uint256 quantity_,
bytes32[] calldata proof_
)
external
view
returns (
address,
address,
bool eligible,
string memory reason
)
{
bytes32 leaf = _getClaimAndTreasuryHash(quantity_, addressToCheck_);
if (MerkleProof.verify(proof_, claimWhitelistMerkleRoot, leaf) == false) {
return (
addressToCheck_,
addressToCheck_,
false,
"Claim mint proof invalid"
);
}
if (_claimHasMinted[addressToCheck_]) {
return (
addressToCheck_,
addressToCheck_,
false,
"Claim: Address has already minted"
);
}
return (addressToCheck_, addressToCheck_, true, "");
}
/**
*
* @dev eligibleForTreasuryMint: Eligibility check for the treasury mint. This can be called from front-end (for example to control
* screen components that indicate if the connected address is eligible).
* Function flow is as follows:
* (1) Check that the quantityEligible and address are in the allowlist.
* (2) Check if this minter is requesting more than its allocation. If so, exit with false eligibility and reason "Treasury: Requesting more than remaining allocation"
* (3) All checks passed, return elibility = true, the delivery address and valid minter adress.
*
*/
function eligibleForTreasuryMint(
address addressToCheck_,
uint256 quantityEligible_,
bytes32[] calldata proof_,
uint256 quantityToMint_
)
external
view
returns (
address,
address,
bool eligible,
string memory reason
)
{
// (2) Check the proof is valid
bytes32 leaf = _getClaimAndTreasuryHash(quantityEligible_, addressToCheck_);
if (
MerkleProof.verify(proof_, treasuryWhitelistMerkleRoot, leaf) == false
) {
return (
addressToCheck_,
addressToCheck_,
false,
"Treasury: mint proof invalid"
);
}
if (
(_treasuryAllocationMinted[addressToCheck_] + quantityToMint_) >
quantityEligible_
) {
return (
addressToCheck_,
addressToCheck_,
false,
"Treasury: Requesting more than remaining allocation"
);
}
return (addressToCheck_, addressToCheck_, true, "");
}
/**
*
* @dev eligibleForCompletionMint: Eligibility check for the completion mint. This can be called from front-end (for example to control
* screen components that indicate if the connected address is eligible).
* Function flow is as follows:
* (1) Check that the quantityEligible, address and unitPrice are in the allowlist.
* (2) Check if this minter is requesting more than its allocation. If so, exit with false eligibility and reason "Treasury: Requesting more than remaining allocation"
* (3) All checks passed, return elibility = true, the delivery address and valid minter adress.
*
*/
function eligibleForCompletionMint(
address addressToCheck_,
uint256 quantityEligible_,
bytes32[] calldata proof_,
uint256 quantityToMint_,
uint256 unitPrice_
)
external
view
returns (
address,
address,
bool eligible,
string memory reason
)
{
bytes32 leaf = _getCompletionHash(
quantityEligible_,
addressToCheck_,
unitPrice_
);
if (
MerkleProof.verify(proof_, completionWhitelistMerkleRoot, leaf) == false
) {
return (
addressToCheck_,
addressToCheck_,
false,
"Completion: mint proof invalid"
);
}
if (
(_completionAllocationMinted[addressToCheck_] + quantityToMint_) >
quantityEligible_
) {
return (
addressToCheck_,
addressToCheck_,
false,
"Completion: Requesting more than remaining allocation"
);
}
return (addressToCheck_, addressToCheck_, true, "");
}
/**
* @dev Burns `tokenId`. See {ERC721-_burn}.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/
function burn(uint256 tokenId) public override {
super.burn(tokenId);
burnCounter += 1;
}
}
SafeERC20.sol 99 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
Pausable.sol 91 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
ERC721Burnable.sol 26 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Burnable.sol)
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "../../../utils/Context.sol";
/**
* @title ERC721 Burnable Token
* @dev ERC721 Token that can be irreversibly burned (destroyed).
*/
abstract contract ERC721Burnable is Context, ERC721 {
/**
* @dev Burns `tokenId`. See {ERC721-_burn}.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/
function burn(uint256 tokenId) public virtual {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
_burn(tokenId);
}
}
IERC721Metadata.sol 27 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
Strings.sol 67 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
IERC721.sol 143 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
ERC165.sol 29 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
Address.sol 217 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
Read Contract
balanceOf 0x70a08231 → uint256
beneficiaryAddress 0xd9c4870e → address
burnCounter 0x4c99007d → uint256
claimWhitelistMerkleRoot 0xd5d0671d → bytes32
communityRandomness 0xb2acde94 → uint256
communityWhitelistLengths 0xe24fe160 → uint256
communityWhitelistMerkleRoot 0xaab99fa0 → bytes32
completionWhitelistMerkleRoot 0x59081cec → bytes32
directWhitelistMerkleRoot 0xac1d1c09 → bytes32
eligibleForClaimMint 0x7dec8b62 → address, address, bool, string
eligibleForCommunityMint 0xe0ba2caf → address, bool, string, bytes32, address
eligibleForCompletionMint 0xfa6a6f6b → address, address, bool, string
eligibleForDirectMint 0x722c632c → address, address, bool, string
eligibleForTreasuryMint 0xdc04602a → address, address, bool, string
getApproved 0x081812fc → address
isApprovedForAll 0xe985e9c5 → bool
listsLocked 0xb3133767 → bool
maxCommunityWhitelistLength 0x99ee0f5f → uint256
maxSupply 0xd5abeb01 → uint256
mintPrice 0x6817c76c → uint256
name 0x06fdde03 → string
numberOfCommunities 0xe1de6710 → uint256
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
pauseCutoffDays 0xe1e20220 → uint256
paused 0x5c975abb → bool
placeholderTokenURI 0x8ecc8083 → string
placeholderTokenURILocked 0x56d8280e → bool
royaltyInfo 0x2a55205a → address, uint256
stage1MintingEnded 0x2b1063c6 → bool
stage1MintingOpen 0x051efeb9 → bool
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenBaseURILocked 0x89852715 → bool
tokenIdCounter 0x98bdf6f5 → uint256
tokenURI 0xc87b56dd → string
totalSupply 0x18160ddd → uint256
treasuryWhitelistMerkleRoot 0xc128aace → bytes32
webaverseLandAddress 0x7ea0f46d → address
webaverseLandAddressLocked 0xea3740e8 → bool
whitelistMintEnd 0x7ab7a9fe → uint256
whitelistMintStart 0xfdda3391 → uint256
Write Contract 34 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address to
uint256 tokenId
burn 0x42966c68
uint256 tokenId
claimMint 0xe43fc992
uint256 quantityToMint_
bytes32[] proof_
uint256[] votes_
communityMint 0xa05bb3c2
uint256 community_
uint256 position_
bytes32[] proof_
uint256[] votes_
completionMint 0x96789548
uint256 quantityEligible_
bytes32[] proof_
uint256 quantityToMint_
uint256 unitPrice_
directMint 0xf04307b1
bytes32[] proof_
uint256[] votes_
getRandomNumber 0xdbdff2c1
No parameters
returns: uint256
lockLandAddress 0x2f2fd170
No parameters
lockLists 0x02eb7976
No parameters
lockPlaceholderTokenURI 0x16fb27fe
No parameters
lockTokenBaseURI 0x82776b9c
No parameters
pause 0x8456cb59
No parameters
rawFulfillRandomWords 0x1fe543e3
uint256 requestId
uint256[] randomWords
renounceOwnership 0x715018a6
No parameters
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes _data
setApprovalForAll 0xa22cb465
address operator
bool approved
setClaimWhitelistMerkleRoot 0xc8e7e619
bytes32 claimWhitelistMerkleRoot_
setCommunityWhitelist 0x1e427660
uint256[] communityWhitelistLengths_
bytes32 communityWhitelistMerkleRoot_
setCompletionWhitelistMerkleRoot 0x952bc525
bytes32 completionWhitelistMerkleRoot_
setDirectWhitelist 0x21fb4a44
bytes32 directWhitelistMerkleRoot_
setLandAddress 0x1e5b2874
address webaverseLandAddress_
setPlaceholderTokenURI 0x12cdee59
string placeholderTokenURI_
setRoyaltyPercentageBasisPoints 0xe042e98c
uint256 royaltyPercentageBasisPoints_
setRoyaltyReceipientAddress 0x009ee39c
address royaltyReceipientAddress_
setTokenBaseURI 0x8ef79e91
string tokenBaseURI_
setTreasuryWhitelistMerkleRoot 0x52357fcf
bytes32 treasuryWhitelistMerkleRoot_
setVRFSubscriptionId 0xd218d95d
uint64 vrfSubscriptionId_
transferERC20Token 0xbcba6939
address token
uint256 amount
transferFrom 0x23b872dd
address from
address to
uint256 tokenId
transferOwnership 0xf2fde38b
address newOwner
treasuryMint 0xa3c12228
uint256 quantityEligible_
bytes32[] proof_
uint256 quantityToMint_
unpause 0x3f4ba83a
No parameters
withdrawContractBalance 0xbfab3db9
No parameters
Recent Transactions
No transactions found for this address