Address Contract Verified
Address
0xa8b6011DdbCe6201E447866fFD5e5FC006fC3F61
Balance
0 ETH
Nonce
1
Code Size
23189 bytes
Creator
0xf97D4230...54e1 at tx 0xa33257ed...0c76c3
Indexed Transactions
0
Contract Bytecode
23189 bytes
0x6080604052600436106104945760003560e01c80638456cb5911610260578063bde750fb11610144578063d5abeb01116100c1578063e985e9c511610085578063e985e9c514610e82578063f29b4fbc14610ea2578063f2fde38b14610ec2578063f7073c3a14610ee2578063f92c45b714610ef7578063ff1473a814610f0e57600080fd5b8063d5abeb0114610de8578063d94917ee14610dfd578063db6c7d3e14610e1d578063de90871f14610e4b578063e7ebdca614610e6b57600080fd5b8063cbccdec311610108578063cbccdec314610d26578063cc5dbcf214610d54578063cd1f5a2914610d7c578063d2c8ed4c14610d93578063d454e0b314610dbb57600080fd5b8063bde750fb14610c74578063c03afb5914610ca2578063c13085db14610cc2578063c87b56dd14610cf3578063c9672e2614610d1357600080fd5b806398ac859e116101dd578063a9a1d6b0116101a1578063a9a1d6b014610ba9578063b1c9fe6e14610bc9578063b2caf79014610bf8578063b7e08d4114610c20578063b7fafcd714610c33578063b88d4fde14610c6157600080fd5b806398ac859e14610af35780639e7b40d614610b1b5780639f7b071c14610b49578063a22cb46514610b69578063a49340cc14610b8957600080fd5b80638da5cb5b116102245780638da5cb5b14610a5b5780638e8a07b314610a79578063910354c214610a9057806395d89b4114610ab05780639831ef2a14610ac557600080fd5b80638456cb59146109c757806384b0196e146109dc578063857b9bd414610a0457806385cb593b14610a1b5780638692810c14610a3b57600080fd5b80633f4ba83a116103875780636c19e7831161030457806373af7a40116102c857806373af7a401461091a57806375d5ae9f1461093a57806375dadb321461095a578063782312a31461096f5780637c5b35a3146109865780638286eee2146109a657600080fd5b80636c19e783146108775780636e820527146108975780636f8b44b0146108c557806370a08231146108e5578063715018a61461090557600080fd5b80635bf6846e1161034b5780635bf6846e146107df5780635c975abb146107ff5780635eff75c1146108175780636352211e146108375780636a00670b1461085757600080fd5b80633f4ba83a1461075257806342842e0e14610767578063481b86ac1461077a5780634bf47ebd1461079157806351cff8d9146107bf57600080fd5b806318160ddd116104155780632cb29a0d116103d95780632cb29a0d146106865780632df507be1461069d5780633886d512146106cb5780633c80c1d1146106fc5780633d8f833d1461072a57600080fd5b806318160ddd146105fd578063238ac9331461061257806323b872dd14610633578063240ff27f1461064657806324d7806c1461066657600080fd5b8063095ea7b31161045c578063095ea7b31461056a578063096cca7d1461057d5780631429fbe4146105a557806315720c5f146105ca578063170e1736146105dd57600080fd5b806301ffc9a714610499578063046211b0146104ce57806306fdde03146104f0578063081812fc14610512578063084b731a1461054a575b600080fd5b3480156104a557600080fd5b506104b96104b4366004614c3a565b610f3c565b60405190151581526020015b60405180910390f35b3480156104da57600080fd5b506104ee6104e9366004614cb0565b610f8e565b005b3480156104fc57600080fd5b506105056111be565b6040516104c59190614d68565b34801561051e57600080fd5b5061053261052d366004614d7b565b611259565b6040516001600160a01b0390911681526020016104c5565b34801561055657600080fd5b506104ee610565366004614dd8565b61129d565b6104ee610578366004614e39565b611365565b34801561058957600080fd5b5061053273e166a1fc32647ba4ec271b753cc56b5f0870d23281565b3480156105b157600080fd5b506105bc6101965481565b6040519081526020016104c5565b6104ee6105d8366004614e65565b611375565b3480156105e957600080fd5b506104ee6105f8366004614d7b565b611d80565b34801561060957600080fd5b506105bc611d8e565b34801561061e57600080fd5b5061019354610532906001600160a01b031681565b6104ee610641366004614ea0565b611dae565b34801561065257600080fd5b506104ee610661366004614eef565b611f7e565b34801561067257600080fd5b506104b9610681366004614f28565b611fce565b34801561069257600080fd5b506105bc6101995481565b3480156106a957600080fd5b506105bc6106b8366004614d7b565b61019d6020526000908152604090205481565b3480156106d757600080fd5b506104b96106e6366004614d7b565b6101a96020526000908152604090205460ff1681565b34801561070857600080fd5b506105bc610717366004614f28565b6101986020526000908152604090205481565b34801561073657600080fd5b5061053273b6a37b5d14d502c3ab0ae6f3a0e058bc9517786e81565b34801561075e57600080fd5b506104ee611fec565b6104ee610775366004614ea0565b611ffe565b34801561078657600080fd5b506105bc61019a5481565b34801561079d57600080fd5b506105bc6107ac366004614d7b565b61019e6020526000908152604090205481565b3480156107cb57600080fd5b506104ee6107da366004614f28565b612019565b3480156107eb57600080fd5b506104ee6107fa366004614ff0565b6120b6565b34801561080b57600080fd5b5060655460ff166104b9565b34801561082357600080fd5b506104ee610832366004614d7b565b6123ff565b34801561084357600080fd5b50610532610852366004614d7b565b61240d565b34801561086357600080fd5b506104ee6108723660046150c4565b612418565b34801561088357600080fd5b506104ee610892366004614f28565b61245e565b3480156108a357600080fd5b506105bc6108b2366004614d7b565b61019f6020526000908152604090205481565b3480156108d157600080fd5b506104ee6108e0366004614d7b565b612489565b3480156108f157600080fd5b506105bc610900366004614f28565b6124b3565b34801561091157600080fd5b506104ee612512565b34801561092657600080fd5b506104ee610935366004614d7b565b612524565b34801561094657600080fd5b506104ee6109553660046150e0565b612532565b34801561096657600080fd5b50610505612565565b34801561097b57600080fd5b506105bc61019c5481565b34801561099257600080fd5b506104ee6109a1366004614d7b565b612575565b3480156109b257600080fd5b506105326c447e69651d841bd8d104bed49381565b3480156109d357600080fd5b506104ee612583565b3480156109e857600080fd5b506109f1612593565b6040516104c59796959493929190615115565b348015610a1057600080fd5b506105bc6101a65481565b348015610a2757600080fd5b506104ee610a363660046150e0565b61265e565b348015610a4757600080fd5b506104ee610a56366004614d7b565b612691565b348015610a6757600080fd5b506033546001600160a01b0316610532565b348015610a8557600080fd5b506105bc6101a35481565b348015610a9c57600080fd5b506104ee610aab366004614d7b565b61269f565b348015610abc57600080fd5b506105056126ad565b348015610ad157600080fd5b506105bc610ae0366004614d7b565b6101976020526000908152604090205481565b348015610aff57600080fd5b50610532733af2a97414d1101e2107a70e7f33955da134630581565b348015610b2757600080fd5b506105bc610b36366004614d7b565b6101a76020526000908152604090205481565b348015610b5557600080fd5b506104ee610b643660046151ae565b6126c5565b348015610b7557600080fd5b506104ee610b84366004614eef565b6128a3565b348015610b9557600080fd5b506104ee610ba43660046151f4565b612920565b348015610bb557600080fd5b506104ee610bc4366004614d7b565b6129f8565b348015610bd557600080fd5b5061019354610beb90600160a01b900460ff1681565b6040516104c59190615293565b348015610c0457600080fd5b5061053273f4a7c105cfdc6aabe9ae65bdf2d0df0a567a7ade81565b6104ee610c2e3660046152a6565b612a06565b348015610c3f57600080fd5b506105bc610c4e36600461535d565b6101946020526000908152604090205481565b6104ee610c6f366004615378565b612d3a565b348015610c8057600080fd5b506105bc610c8f366004614d7b565b6101a46020526000908152604090205481565b348015610cae57600080fd5b506104ee610cbd36600461535d565b612d7b565b348015610cce57600080fd5b50610beb610cdd366004614d7b565b6101956020526000908152604090205460ff1681565b348015610cff57600080fd5b50610505610d0e366004614d7b565b612db1565b6104ee610d21366004614d7b565b612de2565b348015610d3257600080fd5b506105bc610d41366004614f28565b6101a26020526000908152604090205481565b348015610d6057600080fd5b5061053273306b1ea3ecdf94ab739f1910bbda052ed4a9f94981565b348015610d8857600080fd5b506105bc6101a15481565b348015610d9f57600080fd5b5061053273ed5af388653567af2f388e6224dc7c4b3241c54481565b348015610dc757600080fd5b50610ddb610dd6366004614dd8565b612f00565b6040516104c591906153f7565b348015610df457600080fd5b5060fd546105bc565b348015610e0957600080fd5b506104ee610e1836600461543e565b612fcf565b348015610e2957600080fd5b506105bc610e38366004614f28565b6101a86020526000908152604090205481565b348015610e5757600080fd5b506104ee610e66366004614d7b565b613015565b348015610e7757600080fd5b506105bc61019b5481565b348015610e8e57600080fd5b506104b9610e9d366004615463565b613023565b348015610eae57600080fd5b506104ee610ebd366004614d7b565b613045565b348015610ece57600080fd5b506104ee610edd366004614f28565b613053565b348015610eee57600080fd5b506105056130cc565b348015610f0357600080fd5b506105bc6101a55481565b348015610f1a57600080fd5b506105bc610f29366004614d7b565b6101a06020526000908152604090205481565b60006301ffc9a760e01b6001600160e01b031983161480610f6d57506380ac58cd60e01b6001600160e01b03198316145b80610f885750635b5e139f60e01b6001600160e01b03198316145b92915050565b8282826000610f9c846130dc565b90506000610fa9826131d8565b90506000610fed8286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061320592505050565b610193549091506001600160a01b038083169116146110275760405162461bcd60e51b815260040161101e90615491565b60405180910390fd5b60006110338a806154bf565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394506110749250505060208c018c6154bf565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050825185519394509290921491506110f090505760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081c995c5d595cdd608a1b604482015260640161101e565b60005b82518110156111b057600083828151811061111057611110615508565b60200260200101519050600083838151811061112e5761112e615508565b602090810291909101810151600084815261019590925260409091208054919250829160ff191660018360028111156111695761116961525f565b0217905550817f92b778e5d3324b34627600713b43857de3c5f6f8efdcb9435b17198a3888c2dc8260405161119e9190615293565b60405180910390a250506001016110f3565b505050505050505050505050565b60606111c8613221565b60020180546111d69061551e565b80601f01602080910402602001604051908101604052809291908181526020018280546112029061551e565b801561124f5780601f106112245761010080835404028352916020019161124f565b820191906000526020600020905b81548152906001019060200180831161123257829003601f168201915b5050505050905090565b600061126482613245565b611278576112786333d1c03960e21b6132a5565b611280613221565b60009283526006016020525060409020546001600160a01b031690565b60005b818110156113605760008383838181106112bc576112bc615508565b9050602002013590506112ce8161240d565b6001600160a01b0316336001600160a01b0316146112fe5760405162461bcd60e51b815260040161101e90615491565b60008181526101956020526040902080546001919060ff191682800217905550807f92b778e5d3324b34627600713b43857de3c5f6f8efdcb9435b17198a3888c2dc600160405161134f9190615293565b60405180910390a2506001016112a0565b505050565b611371828260016132af565b5050565b60018061019354600160a01b900460ff1660028111156113975761139761525f565b146113b45760405162461bcd60e51b815260040161101e90615552565b6113bc613360565b60006113c883806154bf565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394506114099250505060208501856154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945061144a9250505060408601866154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945061148b9250505060608701876154bf565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394506114cc9250505060808801886154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945061150d9250505060a08901896154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945061154e9250505060c08a018a6154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945061158f9250505060e08b018b6154bf565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509394506115d1925050506101008c018c6154bf565b808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250939450611613925050506101208d018d6154bf565b808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250939450611655925050506101408e018e6154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050905060008d8061016001906116aa91906154bf565b80806020026020016040519081016040528093929190818152602001838360200280828437600092018290525093945083925050505b8d518110156117d05760008e82815181106116fd576116fd615508565b6020026020010151905060008e838151811061171b5761171b615508565b6020026020010151905061172e826133a6565b61019954600083815261019d602052604090205461174d908390615593565b11156117955760405162461bcd60e51b815260206004820152601760248201527610dbcb535d5cd95d5b48195e18d959591cc81b1a5b5a5d604a1b604482015260640161101e565b600082815261019d6020526040812080548392906117b4908490615593565b909155506117c490508185615593565b935050506001016116e0565b5060005b8b518110156118c05760008c82815181106117f1576117f1615508565b6020026020010151905060008c838151811061180f5761180f615508565b6020026020010151905061182282613508565b61019a54600083815261019e6020526040902054611841908390615593565b11156118855760405162461bcd60e51b8152602060048201526013602482015272105e9d5ada48195e18d959591cc81b1a5b5a5d606a1b604482015260640161101e565b600082815261019e6020526040812080548392906118a4908490615593565b909155506118b490508185615593565b935050506001016117d4565b5060005b89518110156119ba5760008a82815181106118e1576118e1615508565b6020026020010151905060008a83815181106118ff576118ff615508565b6020026020010151905061191282613660565b61019b54600083815261019f6020526040902054611931908390615593565b111561197f5760405162461bcd60e51b815260206004820152601d60248201527f417a756b6920656c656d656e74616c2065786365656473206c696d6974000000604482015260640161101e565b600082815261019f60205260408120805483929061199e908490615593565b909155506119ae90508185615593565b935050506001016118c4565b5060005b8751811015611ab45760008882815181106119db576119db615508565b6020026020010151905060008883815181106119f9576119f9615508565b60200260200101519050611a0c826137c2565b61019c5460008381526101a06020526040902054611a2b908390615593565b1115611a795760405162461bcd60e51b815260206004820152601d60248201527f417a756b6920656c656d656e74616c2065786365656473206c696d6974000000604482015260640161101e565b60008281526101a0602052604081208054839290611a98908490615593565b90915550611aa890508185615593565b935050506001016119be565b5060005b8551811015611bae576000868281518110611ad557611ad5615508565b602002602001015190506000868381518110611af357611af3615508565b60200260200101519050611b0682613930565b6101a35460008381526101a46020526040902054611b25908390615593565b1115611b735760405162461bcd60e51b815260206004820152601a60248201527f415243205374656c6c6172732065786365656473206c696d6974000000000000604482015260640161101e565b60008281526101a4602052604081208054839290611b92908490615593565b90915550611ba290508185615593565b93505050600101611ab8565b5060005b8351811015611c9e576000848281518110611bcf57611bcf615508565b602002602001015190506000848381518110611bed57611bed615508565b60200260200101519050611c0082613a92565b6101a65460008381526101a76020526040902054611c1f908390615593565b1115611c635760405162461bcd60e51b81526020600482015260136024820152721099585b9e88195e18d959591cc81b1a5b5a5d606a1b604482015260640161101e565b60008281526101a7602052604081208054839290611c82908490615593565b90915550611c9290508185615593565b93505050600101611bb2565b5060fd54816101a554611cb19190615593565b1115611cf05760405162461bcd60e51b815260206004820152600e60248201526d4578636565647320737570706c7960901b604482015260640161101e565b806101a56000828254611d039190615593565b90915550611d3a905081610194600060015b6002811115611d2657611d2661525f565b815260200190815260200160002054613bea565b60405181815233907f10fcc92ce3ae296b6d2813de054ab2cf2d6dd59a1eed235681bc8bf6c36a5cb79060200160405180910390a2505050505050505050505050505050565b611d88613c77565b6101a555565b60006001611d9a613221565b60010154611da6613221565b540303905090565b6000611db982613cd1565b6001600160a01b039485169490915081168414611ddf57611ddf62a1148160e81b6132a5565b600080611deb84613d94565b91509150611e108187611dfb3390565b6001600160a01b039081169116811491141790565b611e3257611e1e8633613023565b611e3257611e32632ce44b5f60e11b6132a5565b611e3f8686866001613dbc565b8015611e4a57600082555b611e52613221565b6001600160a01b0387166000908152600591909101602052604090208054600019019055611e7e613221565b6001600160a01b03861660008181526005929092016020526040909120805460010190554260a01b17600160e11b17611eb5613221565b60008681526004919091016020526040812091909155600160e11b84169003611f2b5760018401611ee4613221565b600082815260049190910160205260408120549003611f2957611f05613221565b548114611f295783611f15613221565b600083815260049190910160205260409020555b505b6001600160a01b0385168481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a480600003611f7557611f75633a954ecd60e21b6132a5565b50505050505050565b611f8733611fce565b611fa35760405162461bcd60e51b815260040161101e906155a6565b6001600160a01b0391909116600090815260cb60205260409020805460ff1916911515919091179055565b6001600160a01b0316600090815260cb602052604090205460ff1690565b611ff4613c77565b611ffc613e57565b565b61136083838360405180602001604052806000815250612d3a565b612021613c77565b6000816001600160a01b03164760405160006040518083038185875af1925050503d806000811461206e576040519150601f19603f3d011682016040523d82523d6000602084013e612073565b606091505b50509050806113715760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b604482015260640161101e565b600080516020615a4083398151915254610100900460ff166120eb57600080516020615a408339815191525460ff16156120ef565b303b155b6121615760405162461bcd60e51b815260206004820152603760248201527f455243373231415f5f496e697469616c697a61626c653a20636f6e747261637460448201527f20697320616c726561647920696e697469616c697a6564000000000000000000606482015260840161101e565b600080516020615a4083398151915254610100900460ff1615801561219d57600080516020615a40833981519152805461ffff19166101011790555b600054610100900460ff16158080156121bd5750600054600160ff909116105b806121d75750303b1580156121d7575060005460ff166001145b61223a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161101e565b6000805460ff19166001179055801561225d576000805461ff0019166101001790555b612265613ea9565b61226d613ed8565b6122956040518060200160405280600081525060405180602001604052806000815250613f07565b61229f8888613f38565b6122a7613f76565b6122b086613fb9565b6122ba8585613fe0565b6122c2614022565b6122ca614049565b61019380546001600160a81b0319166001600160a01b03851617905561019460205267013c3107490280007fac2681a0ffcdeb8d930437e36dc6669c17d1245fb57aa4cfab8f62b41ea51f818190557f431122e4fe9c44f5a319c6d2afd7cf7bcc21253a0483556b9b40b9255f70a15e819055600260008190527f4f2fafccb5d28f3aaff6cbdf8ff32db4167d35308651b7acedb7127f6ec061859190915561019681905561019981905561019a819055600161019b81905561019c556101a35560056101a15580156123d7576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b508015611f75575050600080516020615a40833981519152805461ff00191690555050505050565b612407613c77565b61019655565b6000610f8882613cd1565b612420613c77565b8061019460008460028111156124385761243861525f565b60028111156124495761244961525f565b81526020810191909152604001600020555050565b612466613c77565b61019380546001600160a01b0319166001600160a01b0392909216919091179055565b61249233611fce565b6124ae5760405162461bcd60e51b815260040161101e906155a6565b60fd55565b60006001600160a01b0382166124d3576124d36323d3ad8160e21b6132a5565b6001600160401b036124e3613221565b6005016000846001600160a01b03166001600160a01b0316815260200190815260200160002054169050919050565b61251a613c77565b611ffc6000614086565b61252c613c77565b61019c55565b61253b33611fce565b6125575760405162461bcd60e51b815260040161101e906155a6565b610130611360828483615614565b606061012f80546111d69061551e565b61257d613c77565b6101a655565b61258b613c77565b611ffc614049565b6000606080600080600060606097546000801b1480156125b35750609854155b6125f75760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b604482015260640161101e565b50506040805180820182526011815270415a554b495f585f434f5f4d555345554d60781b6020808301919091528251808401845260058152640302e312e360dc1b8183015283516000808252928101909452600f60f81b9992985096504695503094509250565b61266733611fce565b6126835760405162461bcd60e51b815260040161101e906155a6565b61012f611360828483615614565b612699613c77565b6101a355565b6126a7613c77565b6101a155565b60606126b7613221565b60030180546111d69061551e565b82828260006126d3846140d8565b905060006126e0826131d8565b905060006127248286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061320592505050565b610193549091506001600160a01b038083169116146127555760405162461bcd60e51b815260040161101e90615491565b6127626020870187614f28565b6001600160a01b0316326001600160a01b0316146127b55760405162461bcd60e51b815260206004820152601060248201526f139bdd08189bdd1cc8185b1b1bddd95960821b604482015260640161101e565b6127c2896020013561240d565b6001600160a01b0316336001600160a01b0316146127f25760405162461bcd60e51b815260040161101e90615491565b6127ff896020013561240d565b6001600160a01b031661281560208b018b614f28565b6001600160a01b03161461283b5760405162461bcd60e51b815260040161101e90615491565b6020898101356000818152610195909252604091829020805460ff19166002908117909155915190917f92b778e5d3324b34627600713b43857de3c5f6f8efdcb9435b17198a3888c2dc916128909190615293565b60405180910390a2505050505050505050565b806128ac613221565b336000818152600792909201602090815260408084206001600160a01b03881680865290835293819020805460ff19169515159590951790945592518415158152919290917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61292933611fce565b6129455760405162461bcd60e51b815260040161101e906155a6565b828181146129955760405162461bcd60e51b815260206004820152601760248201527f41646d696e206d696e743a206261642072657175657374000000000000000000604482015260640161101e565b60005b818110156129f0576129e88686838181106129b5576129b5615508565b90506020020160208101906129ca9190614f28565b8585848181106129dc576129dc615508565b90506020020135614135565b600101612998565b505050505050565b612a00613c77565b61019b55565b838383838315612af7576000612a1b8461413f565b90506000612a28826131d8565b90506000612a6c8286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061320592505050565b610193549091506001600160a01b03808316911614612a9d5760405162461bcd60e51b815260040161101e90615491565b33612aab6020880188614f28565b6001600160a01b031614612af35760405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a59081858d8dbdd5b9d608a1b604482015260640161101e565b5050505b60008061019354600160a01b900460ff166002811115612b1957612b1961525f565b14612b365760405162461bcd60e51b815260040161101e90615552565b612b3e613360565b6000805b8d811015612c2f5760008f8f83818110612b5e57612b5e615508565b90506020020135905060008e8e84818110612b7b57612b7b615508565b905060200201359050612b8d826133a6565b6101965460008381526101976020526040902054612bac908390615593565b1115612bf45760405162461bcd60e51b815260206004820152601760248201527610dbcb535d5cd95d5b48195e18d959591cc81b1a5b5a5d604a1b604482015260640161101e565b6000828152610197602052604081208054839290612c13908490615593565b90915550612c2390508185615593565b93505050600101612b42565b503360009081526101986020908152604090912054908a013590612c54908c90615593565b1115612c9a5760405162461bcd60e51b81526020600482015260156024820152741058d8dbdd5b9d08195e18d959591cc81b1a5b5a5d605a1b604482015260640161101e565b3360009081526101986020526040812080548c9290612cba908490615593565b90915550612cca90508a82615593565b9050612cdb81610194600080611d15565b612ce860208a018a614f28565b6001600160a01b03167f10fcc92ce3ae296b6d2813de054ab2cf2d6dd59a1eed235681bc8bf6c36a5cb782604051612d2291815260200190565b60405180910390a25050505050505050505050505050565b612d45848484611dae565b6001600160a01b0383163b15612d7557612d618484848461416f565b612d7557612d756368d2bf6b60e11b6132a5565b50505050565b612d83613c77565b610193805482919060ff60a01b1916600160a01b836002811115612da957612da961525f565b021790555050565b6060612dbc82613245565b612dd957604051630a14c4b560e41b815260040160405180910390fd5b610f8882614251565b60028061019354600160a01b900460ff166002811115612e0457612e0461525f565b14612e215760405162461bcd60e51b815260040161101e90615552565b612e29613360565b6101a1543360009081526101a26020526040902054612e49908490615593565b1115612e875760405162461bcd60e51b815260206004820152600d60248201526c115e18d959591cc81b1a5b5a5d609a1b604482015260640161101e565b3360009081526101a2602052604081208054849290612ea7908490615593565b90915550612ebd90508261019460006002611d15565b612ec7338361428a565b60405182815233907f10fcc92ce3ae296b6d2813de054ab2cf2d6dd59a1eed235681bc8bf6c36a5cb79060200160405180910390a25050565b60606000826001600160401b03811115612f1c57612f1c614f45565b604051908082528060200260200182016040528015612f45578160200160208202803683370190505b50905060005b83811015612fc7576000858583818110612f6757612f67615508565b6020908102929092013560008181526101959093526040909220549192505060ff166002811115612f9a57612f9a61525f565b838381518110612fac57612fac615508565b60ff9092166020928302919091019091015250600101612f4b565b509392505050565b612fd833611fce565b612ff45760405162461bcd60e51b815260040161101e906155a6565b60009182526101a96020526040909120805460ff1916911515919091179055565b61301d613c77565b61019955565b600061302e82611fce565b8061303e575061303e8383614323565b9392505050565b61304d613c77565b61019a55565b61305b613c77565b6001600160a01b0381166130c05760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161101e565b6130c981614086565b50565b606061013080546111d69061551e565b60007f780db704172bf30eb0a6bf00bb2884f530193152cc89f7a8487c2adb179519d161310983806154bf565b60405160200161311a9291906156d3565b6040516020818303038152906040528051906020012061317a84806020019061314391906154bf565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061436092505050565b60405160200161318a91906156fc565b60408051601f1981840301815282825280516020918201209083019490945281019190915260608101919091526080015b604051602081830303815290604052805190602001209050919050565b6000610f886131e5614413565b8360405161190160f01b8152600281019290925260228201526042902090565b60008060006132148585614422565b91509150612fc781614467565b7f2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4090565b6000816001116132a057613257613221565b548210156132a05760005b61326a613221565b6000848152600491909101602052604081205491508190036132965761328f83615735565b9250613262565b600160e01b161590505b919050565b8060005260046000fd5b60006132ba8361240d565b90508180156132d25750336001600160a01b03821614155b156132f5576132e18133613023565b6132f5576132f56367d9dca160e11b6132a5565b836132fe613221565b6000858152600691909101602052604080822080546001600160a01b0319166001600160a01b0394851617905551859287811692908516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a450505050565b60655460ff1615611ffc5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161101e565b6040516331a9108f60e11b81526004810182905260009073e166a1fc32647ba4ec271b753cc56b5f0870d23290636352211e90602401602060405180830381865afa1580156133f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061341d919061574c565b9050336001600160a01b03821614806134bc5750604051632e7cda1d60e21b81526c447e69651d841bd8d104bed4939063b9f368749061347b903390859073e166a1fc32647ba4ec271b753cc56b5f0870d232908890600401615769565b602060405180830381865afa158015613498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134bc919061579a565b6113715760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420436f2d4d757365756d206f776e6572000000000000000000604482015260640161101e565b6040516331a9108f60e11b81526004810182905260009073ed5af388653567af2f388e6224dc7c4b3241c54490636352211e90602401602060405180830381865afa15801561355b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357f919061574c565b9050336001600160a01b038216148061361e5750604051632e7cda1d60e21b81526c447e69651d841bd8d104bed4939063b9f36874906135dd903390859073ed5af388653567af2f388e6224dc7c4b3241c544908890600401615769565b602060405180830381865afa1580156135fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061361e919061579a565b6113715760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b21020bd3ab5b49037bbb732b960691b604482015260640161101e565b6040516331a9108f60e11b81526004810182905260009073b6a37b5d14d502c3ab0ae6f3a0e058bc9517786e90636352211e90602401602060405180830381865afa1580156136b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d7919061574c565b9050336001600160a01b03821614806137765750604051632e7cda1d60e21b81526c447e69651d841bd8d104bed4939063b9f3687490613735903390859073b6a37b5d14d502c3ab0ae6f3a0e058bc9517786e908890600401615769565b602060405180830381865afa158015613752573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613776919061579a565b6113715760405162461bcd60e51b815260206004820152601e60248201527f496e76616c696420417a756b6920656c656d656e74616c73206f776e65720000604482015260640161101e565b6040516331a9108f60e11b815260048101829052600090733af2a97414d1101e2107a70e7f33955da134630590636352211e90602401602060405180830381865afa158015613815573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613839919061574c565b9050336001600160a01b03821614806138d85750604051632e7cda1d60e21b81526c447e69651d841bd8d104bed4939063b9f36874906138979033908590733af2a97414d1101e2107a70e7f33955da1346305908890600401615769565b602060405180830381865afa1580156138b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d8919061579a565b6113715760405162461bcd60e51b815260206004820152602360248201527f496e76616c696420417a756b6920656c656d656e74616c206265616e7a206f776044820152623732b960e91b606482015260840161101e565b6040516331a9108f60e11b81526004810182905260009073f4a7c105cfdc6aabe9ae65bdf2d0df0a567a7ade90636352211e90602401602060405180830381865afa158015613983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139a7919061574c565b9050336001600160a01b0382161480613a465750604051632e7cda1d60e21b81526c447e69651d841bd8d104bed4939063b9f3687490613a05903390859073f4a7c105cfdc6aabe9ae65bdf2d0df0a567a7ade908890600401615769565b602060405180830381865afa158015613a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a46919061579a565b6113715760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420415243205374656c6c617273206f776e6572000000000000604482015260640161101e565b6040516331a9108f60e11b81526004810182905260009073306b1ea3ecdf94ab739f1910bbda052ed4a9f94990636352211e90602401602060405180830381865afa158015613ae5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b09919061574c565b9050336001600160a01b0382161480613ba85750604051632e7cda1d60e21b81526c447e69651d841bd8d104bed4939063b9f3687490613b67903390859073306b1ea3ecdf94ab739f1910bbda052ed4a9f949908890600401615769565b602060405180830381865afa158015613b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba8919061579a565b6113715760405162461bcd60e51b815260206004820152601360248201527224b73b30b634b2102132b0b73d1037bbb732b960691b604482015260640161101e565b6000613bf682846157b7565b905080341015613c395760405162461bcd60e51b815260206004820152600e60248201526d09cdee840cadcdeeaced0408aa8960931b604482015260640161101e565b8034111561136057336108fc613c4f83346157ce565b6040518115909202916000818181858888f19350505050158015612d75573d6000803e3d6000fd5b6033546001600160a01b03163314611ffc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161101e565b600081600111613d8457613ce3613221565b60008381526004919091016020526040902054905080600003613d7157613d08613221565b548210613d1f57613d1f636f96cda160e11b6132a5565b613d27613221565b600019909201600081815260049390930160205260409092205490508015613d1f57600160e01b8116600003613d5c57919050565b613d6c636f96cda160e11b6132a5565b613d1f565b600160e01b8116600003613d8457919050565b6132a0636f96cda160e11b6132a5565b6000806000613da1613221565b60009485526006016020525050604090912080549092909150565b60008281526101a9602052604090205460ff16613e52576001600160a01b0384161580613e0d575060016000838152610195602052604090205460ff166002811115613e0a57613e0a61525f565b14155b613e525760405162461bcd60e51b8152602060048201526016602482015275546f6b656e206e6f74207472616e7366657261626c6560501b604482015260640161101e565b612d75565b613e5f6145b1565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600054610100900460ff16613ed05760405162461bcd60e51b815260040161101e906157e1565b611ffc6145fa565b600054610100900460ff16613eff5760405162461bcd60e51b815260040161101e906157e1565b611ffc61462a565b600054610100900460ff16613f2e5760405162461bcd60e51b815260040161101e906157e1565b611371828261465d565b600080516020615a4083398151915254610100900460ff16613f6c5760405162461bcd60e51b815260040161101e9061582c565b61137182826146ac565b600054610100900460ff16613f9d5760405162461bcd60e51b815260040161101e906157e1565b33600090815260cb60205260409020805460ff19166001179055565b600054610100900460ff166124ae5760405162461bcd60e51b815260040161101e906157e1565b600054610100900460ff166140075760405162461bcd60e51b815260040161101e906157e1565b61012f6140148382615880565b506101306113608282615880565b600054610100900460ff16611ffc5760405162461bcd60e51b815260040161101e906157e1565b614051613360565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613e8c3390565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f174f0379daebafd8e67e77e1e123fa4d557714088db998118cd0a5f0137671cf6141086020840184614f28565b604080516020818101949094526001600160a01b03909216908201529083013560608201526080016131bb565b611371828261428a565b60007f904116aebab2081d38d8cae3b4fbc5c844749e354a61c1001bc4c71f06596cb26141086020840184614f28565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906141a490339089908890889060040161593f565b6020604051808303816000875af19250505080156141df575060408051601f3d908101601f191682019092526141dc9181019061597c565b60015b614234573d80801561420d576040519150601f19603f3d011682016040523d82523d6000602084013e614212565b606091505b50805160000361422c5761422c6368d2bf6b60e11b6132a5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b606061012f61425f8361471f565b61013060405160200161427493929190615a0c565b6040516020818303038152906040529050919050565b8060fd54816142976147b1565b6142a19190615593565b11156142e05760405162461bcd60e51b815260206004820152600e60248201526d4578636565647320737570706c7960901b604482015260640161101e565b3233146143195760405162461bcd60e51b81526020600482015260076024820152664e6f20626f747360c81b604482015260640161101e565b61136083836147bb565b600061432d613221565b6001600160a01b039384166000908152600791909101602090815260408083209490951682529290925250205460ff1690565b6060600082516001600160401b0381111561437d5761437d614f45565b6040519080825280602002602001820160405280156143a6578160200160208202803683370190505b50905060005b835181101561440c578381815181106143c7576143c7615508565b602002602001015160028111156143e0576143e061525f565b8282815181106143f2576143f2615508565b60ff909216602092830291909101909101526001016143ac565b5092915050565b600061441d6147d5565b905090565b60008082516041036144585760208301516040840151606085015160001a61444c87828585614849565b94509450505050614460565b506000905060025b9250929050565b600081600481111561447b5761447b61525f565b036144835750565b60018160048111156144975761449761525f565b036144e45760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161101e565b60028160048111156144f8576144f861525f565b036145455760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161101e565b60038160048111156145595761455961525f565b036130c95760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161101e565b60655460ff16611ffc5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161101e565b600054610100900460ff166146215760405162461bcd60e51b815260040161101e906157e1565b611ffc33614086565b600054610100900460ff166146515760405162461bcd60e51b815260040161101e906157e1565b6065805460ff19169055565b600054610100900460ff166146845760405162461bcd60e51b815260040161101e906157e1565b60996146908382615880565b50609a61469d8282615880565b50506000609781905560985550565b600080516020615a4083398151915254610100900460ff166146e05760405162461bcd60e51b815260040161101e9061582c565b816146e9613221565b600201906146f79082615880565b5080614701613221565b6003019061470f9082615880565b50600161471a613221565b555050565b6060600061472c8361490d565b60010190506000816001600160401b0381111561474b5761474b614f45565b6040519080825280601f01601f191660200182016040528015614775576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461477f57509392505050565b600061441d611d8e565b6113718282604051806020016040528060008152506149e5565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f614800614a59565b614808614ad8565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156148805750600090506003614904565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156148d4573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166148fd57600060019250925050614904565b9150600090505b94509492505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061494c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef81000000008310614978576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061499657662386f26fc10000830492506010015b6305f5e10083106149ae576305f5e100830492506008015b61271083106149c257612710830492506004015b606483106149d4576064830492506002015b600a8310610f885760010192915050565b6149ef8383614b23565b6001600160a01b0383163b15611360576000614a09613221565b5490508281035b614a23600086838060010194508661416f565b614a3757614a376368d2bf6b60e11b6132a5565b818110614a105781614a47613221565b5414614a5257600080fd5b5050505050565b600080614a8a604080518082019091526011815270415a554b495f585f434f5f4d555345554d60781b602082015290565b805190915015614aa1578051602090910120919050565b6097548015614ab05792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b600080614afd6040805180820190915260058152640302e312e360dc1b602082015290565b805190915015614b14578051602090910120919050565b6098548015614ab05792915050565b6000614b2d613221565b5490506000829003614b4957614b4963b562e8dd60e01b6132a5565b614b566000848385613dbc565b6001600160a01b0383164260a01b6001841460e11b1717614b75613221565b60008381526004919091016020526040902055680100000000000000018202614b9c613221565b6001600160a01b0385166000818152600592909201602052604082208054909301909255819003614bd657614bd6622e076360e81b6132a5565b818301825b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4818160010191508103614bdb5781614c1a613221565b5550611360915050565b6001600160e01b0319811681146130c957600080fd5b600060208284031215614c4c57600080fd5b813561303e81614c24565b600060408284031215614c6957600080fd5b50919050565b60008083601f840112614c8157600080fd5b5081356001600160401b03811115614c9857600080fd5b60208301915083602082850101111561446057600080fd5b600080600060408486031215614cc557600080fd5b83356001600160401b0380821115614cdc57600080fd5b614ce887838801614c57565b94506020860135915080821115614cfe57600080fd5b50614d0b86828701614c6f565b9497909650939450505050565b60005b83811015614d33578181015183820152602001614d1b565b50506000910152565b60008151808452614d54816020860160208601614d18565b601f01601f19169290920160200192915050565b60208152600061303e6020830184614d3c565b600060208284031215614d8d57600080fd5b5035919050565b60008083601f840112614da657600080fd5b5081356001600160401b03811115614dbd57600080fd5b6020830191508360208260051b850101111561446057600080fd5b60008060208385031215614deb57600080fd5b82356001600160401b03811115614e0157600080fd5b614e0d85828601614d94565b90969095509350505050565b6001600160a01b03811681146130c957600080fd5b80356132a081614e19565b60008060408385031215614e4c57600080fd5b8235614e5781614e19565b946020939093013593505050565b600060208284031215614e7757600080fd5b81356001600160401b03811115614e8d57600080fd5b8201610180818503121561303e57600080fd5b600080600060608486031215614eb557600080fd5b8335614ec081614e19565b92506020840135614ed081614e19565b929592945050506040919091013590565b80151581146130c957600080fd5b60008060408385031215614f0257600080fd5b8235614f0d81614e19565b91506020830135614f1d81614ee1565b809150509250929050565b600060208284031215614f3a57600080fd5b813561303e81614e19565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115614f7557614f75614f45565b604051601f8501601f19908116603f01168101908282118183101715614f9d57614f9d614f45565b81604052809350858152868686011115614fb657600080fd5b858560208301376000602087830101525050509392505050565b600082601f830112614fe157600080fd5b61303e83833560208501614f5b565b60008060008060008060c0878903121561500957600080fd5b86356001600160401b038082111561502057600080fd5b61502c8a838b01614fd0565b9750602089013591508082111561504257600080fd5b61504e8a838b01614fd0565b965060408901359550606089013591508082111561506b57600080fd5b6150778a838b01614fd0565b9450608089013591508082111561508d57600080fd5b5061509a89828a01614fd0565b9250506150a960a08801614e2e565b90509295509295509295565b8035600381106132a057600080fd5b600080604083850312156150d757600080fd5b614e57836150b5565b600080602083850312156150f357600080fd5b82356001600160401b0381111561510957600080fd5b614e0d85828601614c6f565b60ff60f81b881681526000602060e0602084015261513660e084018a614d3c565b8381036040850152615148818a614d3c565b606085018990526001600160a01b038816608086015260a0850187905284810360c08601528551808252602080880193509091019060005b8181101561519c57835183529284019291840191600101615180565b50909c9b505050505050505050505050565b6000806000606084860312156151c357600080fd5b6151cd8585614c57565b925060408401356001600160401b038111156151e857600080fd5b614d0b86828701614c6f565b6000806000806040858703121561520a57600080fd5b84356001600160401b038082111561522157600080fd5b61522d88838901614d94565b9096509450602087013591508082111561524657600080fd5b5061525387828801614d94565b95989497509550505050565b634e487b7160e01b600052602160045260246000fd5b600381106130c957634e487b7160e01b600052602160045260246000fd5b602081016152a083615275565b91905290565b60008060008060008060008060c0898b0312156152c257600080fd5b88356001600160401b03808211156152d957600080fd5b6152e58c838d01614d94565b909a50985060208b01359150808211156152fe57600080fd5b61530a8c838d01614d94565b909850965060408b013595508691506153268c60608d01614c57565b945060a08b013591508082111561533c57600080fd5b506153498b828c01614c6f565b999c989b5096995094979396929594505050565b60006020828403121561536f57600080fd5b61303e826150b5565b6000806000806080858703121561538e57600080fd5b843561539981614e19565b935060208501356153a981614e19565b92506040850135915060608501356001600160401b038111156153cb57600080fd5b8501601f810187136153dc57600080fd5b6153eb87823560208401614f5b565b91505092959194509250565b6020808252825182820181905260009190848201906040850190845b8181101561543257835160ff1683529284019291840191600101615413565b50909695505050505050565b6000806040838503121561545157600080fd5b823591506020830135614f1d81614ee1565b6000806040838503121561547657600080fd5b823561548181614e19565b91506020830135614f1d81614e19565b602080825260149082015273155b985d5d1a1bdc9a5e9959081c995c5d595cdd60621b604082015260600190565b6000808335601e198436030181126154d657600080fd5b8301803591506001600160401b038211156154f057600080fd5b6020019150600581901b360382131561446057600080fd5b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061553257607f821691505b602082108103614c6957634e487b7160e01b600052602260045260246000fd5b602080825260119082015270141a185cd9481b9bdd08195b98589b1959607a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f8857610f8861557d565b6020808252600c908201526b2737ba1030b71030b236b4b760a11b604082015260600190565b601f821115611360576000816000526020600020601f850160051c810160208610156155f55750805b601f850160051c820191505b818110156129f057828155600101615601565b6001600160401b0383111561562b5761562b614f45565b61563f83615639835461551e565b836155cc565b6000601f841160018114615673576000851561565b5750838201355b600019600387901b1c1916600186901b178355614a52565b600083815260209020601f19861690835b828110156156a45786850135825560209485019460019092019101615684565b50868210156156c15760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60006001600160fb1b038311156156e957600080fd5b8260051b80858437919091019392505050565b815160009082906020808601845b8381101561572957815160ff168552938201939082019060010161570a565b50929695505050505050565b6000816157445761574461557d565b506000190190565b60006020828403121561575e57600080fd5b815161303e81614e19565b6001600160a01b03948516815292841660208401529216604082015260608101919091526000608082015260a00190565b6000602082840312156157ac57600080fd5b815161303e81614ee1565b8082028115828204841417610f8857610f8861557d565b81810381811115610f8857610f8861557d565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526034908201527f455243373231415f5f496e697469616c697a61626c653a20636f6e7472616374604082015273206973206e6f7420696e697469616c697a696e6760601b606082015260800190565b81516001600160401b0381111561589957615899614f45565b6158ad816158a7845461551e565b846155cc565b602080601f8311600181146158e257600084156158ca5750858301515b600019600386901b1c1916600185901b1785556129f0565b600085815260208120601f198616915b82811015615911578886015182559484019460019091019084016158f2565b508582101561592f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061597290830184614d3c565b9695505050505050565b60006020828403121561598e57600080fd5b815161303e81614c24565b600081546159a68161551e565b600182811680156159be57600181146159d357615a02565b60ff1984168752821515830287019450615a02565b8560005260208060002060005b858110156159f95781548a8201529084019082016159e0565b50505082870194505b5050505092915050565b6000615a188286615999565b8451615a28818360208901614d18565b615a3481830186615999565b97965050505050505056feee151c8401928dc223602bb187aff91b9a56c7cae5476ef1b3287b085a16c85fa264697066735822122053a0f47141533ec92ebc909171f9833684e89ba08682abc0f91c5a0b82d3fa9664736f6c63430008180033
Verified Source Code Full Match
Compiler: v0.8.24+commit.e11b9ed9
EVM: paris
Optimization: Yes (200 runs)
OwnableUpgradeable.sol 95 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling 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);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
IERC5267Upgradeable.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol)
pragma solidity ^0.8.0;
interface IERC5267Upgradeable {
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/
event EIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}
Initializable.sol 166 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
PausableUpgradeable.sol 117 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.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 PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @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.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
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());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
IERC721Upgradeable.sol 132 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721Upgradeable is IERC165Upgradeable {
/**
* @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`.
*
* 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;
/**
* @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* 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 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 the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @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);
}
AddressUpgradeable.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or 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 {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
ContextUpgradeable.sol 41 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
ECDSAUpgradeable.sol 217 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../StringsUpgradeable.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
EIP712Upgradeable.sol 205 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.8;
import "./ECDSAUpgradeable.sol";
import "../../interfaces/IERC5267Upgradeable.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
* separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the
* separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
*
* _Available since v3.4._
*
* @custom:storage-size 52
*/
abstract contract EIP712Upgradeable is Initializable, IERC5267Upgradeable {
bytes32 private constant _TYPE_HASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
/// @custom:oz-renamed-from _HASHED_NAME
bytes32 private _hashedName;
/// @custom:oz-renamed-from _HASHED_VERSION
bytes32 private _hashedVersion;
string private _name;
string private _version;
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
function __EIP712_init(string memory name, string memory version) internal onlyInitializing {
__EIP712_init_unchained(name, version);
}
function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {
_name = name;
_version = version;
// Reset prior values in storage if upgrading
_hashedName = 0;
_hashedVersion = 0;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
return _buildDomainSeparator();
}
function _buildDomainSeparator() private view returns (bytes32) {
return keccak256(abi.encode(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev See {EIP-5267}.
*
* _Available since v4.9._
*/
function eip712Domain()
public
view
virtual
override
returns (
bytes1 fields,
string memory name,
string memory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
// If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized
// and the EIP712 domain is not reliable, as it will be missing name and version.
require(_hashedName == 0 && _hashedVersion == 0, "EIP712: Uninitialized");
return (
hex"0f", // 01111
_EIP712Name(),
_EIP712Version(),
block.chainid,
address(this),
bytes32(0),
new uint256[](0)
);
}
/**
* @dev The name parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712Name() internal virtual view returns (string memory) {
return _name;
}
/**
* @dev The version parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712Version() internal virtual view returns (string memory) {
return _version;
}
/**
* @dev The hash of the name parameter for the EIP712 domain.
*
* NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead.
*/
function _EIP712NameHash() internal view returns (bytes32) {
string memory name = _EIP712Name();
if (bytes(name).length > 0) {
return keccak256(bytes(name));
} else {
// If the name is empty, the contract may have been upgraded without initializing the new storage.
// We return the name hash in storage if non-zero, otherwise we assume the name is empty by design.
bytes32 hashedName = _hashedName;
if (hashedName != 0) {
return hashedName;
} else {
return keccak256("");
}
}
}
/**
* @dev The hash of the version parameter for the EIP712 domain.
*
* NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead.
*/
function _EIP712VersionHash() internal view returns (bytes32) {
string memory version = _EIP712Version();
if (bytes(version).length > 0) {
return keccak256(bytes(version));
} else {
// If the version is empty, the contract may have been upgraded without initializing the new storage.
// We return the version hash in storage if non-zero, otherwise we assume the version is empty by design.
bytes32 hashedVersion = _hashedVersion;
if (hashedVersion != 0) {
return hashedVersion;
} else {
return keccak256("");
}
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[48] private __gap;
}
IERC165Upgradeable.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 IERC165Upgradeable {
/**
* @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);
}
MathUpgradeable.sol 339 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
SignedMathUpgradeable.sol 43 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMathUpgradeable {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}
StringsUpgradeable.sol 85 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/MathUpgradeable.sol";
import "./math/SignedMathUpgradeable.sol";
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = MathUpgradeable.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, MathUpgradeable.log256(value) + 1);
}
}
/**
* @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] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
AdminManagerUpgradable.sol 34 lines
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract AdminManagerUpgradable is Initializable {
mapping(address => bool) private _admins;
function __AdminManager_init() internal onlyInitializing {
__AdminManager_init_unchained();
}
function __AdminManager_init_unchained() internal onlyInitializing {
_admins[msg.sender] = true;
}
function setAdminPermissions(
address account_,
bool enable_
) external onlyAdmin {
_admins[account_] = enable_;
}
function isAdmin(address account_) public view returns (bool) {
return _admins[account_];
}
modifier onlyAdmin() {
require(isAdmin(msg.sender), "Not an admin");
_;
}
uint256[49] private __gap;
}
AdminMintUpgradable.sol 30 lines
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./AdminManagerUpgradable.sol";
abstract contract AdminMintUpgradable is Initializable, AdminManagerUpgradable {
function __AdminMint_init() internal onlyInitializing {
__AdminManager_init_unchained();
__AdminMint_init_unchained();
}
function __AdminMint_init_unchained() internal onlyInitializing {}
function adminMint(
address[] calldata accounts_,
uint256[] calldata amounts_
) external onlyAdmin {
uint256 accountsLength = accounts_.length;
require(accountsLength == amounts_.length, "Admin mint: bad request");
for (uint256 i; i < accountsLength; i++) {
_adminMint(accounts_[i], amounts_[i]);
}
}
function _adminMint(address account_, uint256 amount_) internal virtual;
uint256[50] private __gap;
}
IDelegateRegistry.sol 318 lines
// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.8.13;
/**
* @title IDelegateRegistry
* @custom:version 2.0
* @custom:author foobar (0xfoobar)
* @notice A standalone immutable registry storing delegated permissions from one address to another
*/
interface IDelegateRegistry {
/// @notice Delegation type, NONE is used when a delegation does not exist or is revoked
enum DelegationType {
NONE,
ALL,
CONTRACT,
ERC721,
ERC20,
ERC1155
}
/// @notice Struct for returning delegations
struct Delegation {
DelegationType type_;
address to;
address from;
bytes32 rights;
address contract_;
uint256 tokenId;
uint256 amount;
}
/// @notice Emitted when an address delegates or revokes rights for their entire wallet
event DelegateAll(
address indexed from,
address indexed to,
bytes32 rights,
bool enable
);
/// @notice Emitted when an address delegates or revokes rights for a contract address
event DelegateContract(
address indexed from,
address indexed to,
address indexed contract_,
bytes32 rights,
bool enable
);
/// @notice Emitted when an address delegates or revokes rights for an ERC721 tokenId
event DelegateERC721(
address indexed from,
address indexed to,
address indexed contract_,
uint256 tokenId,
bytes32 rights,
bool enable
);
/// @notice Emitted when an address delegates or revokes rights for an amount of ERC20 tokens
event DelegateERC20(
address indexed from,
address indexed to,
address indexed contract_,
bytes32 rights,
uint256 amount
);
/// @notice Emitted when an address delegates or revokes rights for an amount of an ERC1155 tokenId
event DelegateERC1155(
address indexed from,
address indexed to,
address indexed contract_,
uint256 tokenId,
bytes32 rights,
uint256 amount
);
/// @notice Thrown if multicall calldata is malformed
error MulticallFailed();
/**
* ----------- WRITE -----------
*/
/**
* @notice Call multiple functions in the current contract and return the data from all of them if they all succeed
* @param data The encoded function data for each of the calls to make to this contract
* @return results The results from each of the calls passed in via data
*/
function multicall(
bytes[] calldata data
) external payable returns (bytes[] memory results);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for all contracts
* @param to The address to act as delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateAll(
address to,
bytes32 rights,
bool enable
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific contract
* @param to The address to act as delegate
* @param contract_ The contract whose rights are being delegated
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateContract(
address to,
address contract_,
bytes32 rights,
bool enable
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific ERC721 token
* @param to The address to act as delegate
* @param contract_ The contract whose rights are being delegated
* @param tokenId The token id to delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param enable Whether to enable or disable this delegation, true delegates and false revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC721(
address to,
address contract_,
uint256 tokenId,
bytes32 rights,
bool enable
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC20 tokens
* @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
* @param to The address to act as delegate
* @param contract_ The address for the fungible token contract
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param amount The amount to delegate, > 0 delegates and 0 revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC20(
address to,
address contract_,
bytes32 rights,
uint256 amount
) external payable returns (bytes32 delegationHash);
/**
* @notice Allow the delegate to act on behalf of `msg.sender` for a specific amount of ERC1155 tokens
* @dev The actual amount is not encoded in the hash, just the existence of a amount (since it is an upper bound)
* @param to The address to act as delegate
* @param contract_ The address of the contract that holds the token
* @param tokenId The token id to delegate
* @param rights Specific subdelegation rights granted to the delegate, pass an empty bytestring to encompass all rights
* @param amount The amount of that token id to delegate, > 0 delegates and 0 revokes
* @return delegationHash The unique identifier of the delegation
*/
function delegateERC1155(
address to,
address contract_,
uint256 tokenId,
bytes32 rights,
uint256 amount
) external payable returns (bytes32 delegationHash);
/**
* ----------- CHECKS -----------
*/
/**
* @notice Check if `to` is a delegate of `from` for the entire wallet
* @param to The potential delegate address
* @param from The potential address who delegated rights
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on the from's behalf
*/
function checkDelegateForAll(
address to,
address from,
bytes32 rights
) external view returns (bool);
/**
* @notice Check if `to` is a delegate of `from` for the specified `contract_` or the entire wallet
* @param to The delegated address to check
* @param contract_ The specific contract address being checked
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on from's behalf for entire wallet or that specific contract
*/
function checkDelegateForContract(
address to,
address from,
address contract_,
bytes32 rights
) external view returns (bool);
/**
* @notice Check if `to` is a delegate of `from` for the specific `contract` and `tokenId`, the entire `contract_`, or the entire wallet
* @param to The delegated address to check
* @param contract_ The specific contract address being checked
* @param tokenId The token id for the token to delegating
* @param from The wallet that issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return valid Whether delegate is granted to act on from's behalf for entire wallet, that contract, or that specific tokenId
*/
function checkDelegateForERC721(
address to,
address from,
address contract_,
uint256 tokenId,
bytes32 rights
) external view returns (bool);
/**
* @notice Returns the amount of ERC20 tokens the delegate is granted rights to act on the behalf of
* @param to The delegated address to check
* @param contract_ The address of the token contract
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return balance The delegated balance, which will be 0 if the delegation does not exist
*/
function checkDelegateForERC20(
address to,
address from,
address contract_,
bytes32 rights
) external view returns (uint256);
/**
* @notice Returns the amount of a ERC1155 tokens the delegate is granted rights to act on the behalf of
* @param to The delegated address to check
* @param contract_ The address of the token contract
* @param tokenId The token id to check the delegated amount of
* @param from The cold wallet who issued the delegation
* @param rights Specific rights to check for, pass the zero value to ignore subdelegations and check full delegations only
* @return balance The delegated balance, which will be 0 if the delegation does not exist
*/
function checkDelegateForERC1155(
address to,
address from,
address contract_,
uint256 tokenId,
bytes32 rights
) external view returns (uint256);
/**
* ----------- ENUMERATIONS -----------
*/
/**
* @notice Returns all enabled delegations a given delegate has received
* @param to The address to retrieve delegations for
* @return delegations Array of Delegation structs
*/
function getIncomingDelegations(
address to
) external view returns (Delegation[] memory delegations);
/**
* @notice Returns all enabled delegations an address has given out
* @param from The address to retrieve delegations for
* @return delegations Array of Delegation structs
*/
function getOutgoingDelegations(
address from
) external view returns (Delegation[] memory delegations);
/**
* @notice Returns all hashes associated with enabled delegations an address has received
* @param to The address to retrieve incoming delegation hashes for
* @return delegationHashes Array of delegation hashes
*/
function getIncomingDelegationHashes(
address to
) external view returns (bytes32[] memory delegationHashes);
/**
* @notice Returns all hashes associated with enabled delegations an address has given out
* @param from The address to retrieve outgoing delegation hashes for
* @return delegationHashes Array of delegation hashes
*/
function getOutgoingDelegationHashes(
address from
) external view returns (bytes32[] memory delegationHashes);
/**
* @notice Returns the delegations for a given array of delegation hashes
* @param delegationHashes is an array of hashes that correspond to delegations
* @return delegations Array of Delegation structs, return empty structs for nonexistent or revoked delegations
*/
function getDelegationsFromHashes(
bytes32[] calldata delegationHashes
) external view returns (Delegation[] memory delegations);
/**
* ----------- STORAGE ACCESS -----------
*/
/**
* @notice Allows external contracts to read arbitrary storage slots
*/
function readSlot(bytes32 location) external view returns (bytes32);
/**
* @notice Allows external contracts to read an arbitrary array of storage slots
*/
function readSlots(
bytes32[] calldata locations
) external view returns (bytes32[] memory);
}
NFTSale.sol 717 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
import "erc721a-upgradeable/contracts/ERC721AUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "./interfaces/IDelegateRegistry.sol";
import "./SupplyUpgradable.sol";
import "./UriManagerUpgradable.sol";
import "./AdminMintUpgradable.sol";
contract NFTSale is
Initializable,
OwnableUpgradeable,
PausableUpgradeable,
EIP712Upgradeable,
ERC721AUpgradeable,
SupplyUpgradable,
UriManagerUpgradable,
AdminMintUpgradable
{
// External contracts
IERC721Upgradeable public constant CO_MUSEUM =
IERC721Upgradeable(0xE166A1fC32647ba4eC271B753cC56B5F0870d232);
IERC721Upgradeable public constant AZUKI =
IERC721Upgradeable(0xED5AF388653567Af2F388E6224dC7C4b3241C544);
IERC721Upgradeable public constant AZUKI_BEANZ =
IERC721Upgradeable(0x306b1ea3ecdf94aB739F1910bbda052Ed4A9f949);
IERC721Upgradeable public constant AZUKI_ELEMENTALS =
IERC721Upgradeable(0xB6a37b5d14D502c3Ab0Ae6f3a0E058BC9517786e);
IERC721Upgradeable public constant AZUKI_ELEMENTAL_BEANZ =
IERC721Upgradeable(0x3Af2A97414d1101E2107a70E7F33955da1346305);
IERC721Upgradeable public constant ARC_STELLARS =
IERC721Upgradeable(0xf4A7C105CFdc6aaBe9AE65bDF2d0dF0A567A7aDE);
IDelegateRegistry public constant DELEGATE_REGISTRY =
IDelegateRegistry(0x00000000000000447e69651d841bD8D104Bed493);
// General mint configurations
address public signer;
Phase public phase;
mapping(Phase => uint256) public price;
mapping(uint256 => TokenPhase) public tokenPhases;
// Presale configurations
uint256 public presaleCoMuseumLimit;
mapping(uint256 => uint256) public presaleCoMuseumBalances;
mapping(address => uint256) public presaleAccountBalances;
// Sale one configurations
uint256 public saleOneCoMuseumLimit;
uint256 public saleOneAzukiLimit;
uint256 public saleOneAzukiElementalsLimit;
uint256 public saleOneAzukiElementalBeanzLimit;
mapping(uint256 => uint256) public saleOneCoMuseumBalances;
mapping(uint256 => uint256) public saleOneAzukiBalances;
mapping(uint256 => uint256) public saleOneAzukiElementalsBalances;
mapping(uint256 => uint256) public saleOneAzukiElementalBeanzBalances;
// Sale two configurations
uint256 public saleTwoAccountLimit;
mapping(address => uint256) public saleTwoAccountBalances;
uint256 public saleOneArcStellarsLimit;
mapping(uint256 => uint256) public saleOneArcStellarsBalances;
uint256 public reservedAmount;
uint256 public saleOneBeanzLimit;
mapping(uint256 => uint256) public saleOneBeanzBalances;
mapping(address => uint256) public claimNonces;
mapping(uint256 => bool) public allowedTransfers;
enum TokenPhase {
Minted,
Claimed,
Decoupled
}
enum Phase {
Presale,
SaleOne,
SaleTwo
}
struct PresaleRequest {
address account;
uint256 limit;
}
struct SaleOneRequest {
uint256[] coMuseumIds;
uint256[] coMuseumAmounts;
uint256[] azukiIds;
uint256[] azukiAmounts;
uint256[] azukiElementalsIds;
uint256[] azukiElementalsAmounts;
uint256[] azukiElementalBeanzIds;
uint256[] azukiElementalBeanzAmounts;
uint256[] arcStellarsIds;
uint256[] arcStellarsAmounts;
uint256[] beanzIds;
uint256[] beanzAmounts;
}
struct SetTokenPhaseRequest {
uint256[] tokenIds;
TokenPhase[] phases;
}
struct DecoupleTokenRequest {
address account;
uint256 tokenId;
}
event Presale(address indexed account, uint256 amount);
event TokenPhaseChange(uint256 indexed tokenId, TokenPhase tokenPhase);
bytes32 private constant PRESALE_REQUEST_TYPE_HASH =
keccak256("PresaleRequest(address account,uint256 limit)");
bytes32 private constant SET_TOKEN_PHASE_REQUEST_TYPE_HASH =
keccak256("SetTokenPhaseRequest(uint256[] tokenIds,uint8[] phases)");
bytes32 private constant DECOUPLE_TOKEN_PHASE_REQUEST_TYPE_HASH =
keccak256("DecoupleTokenRequest(address account,uint256 tokenId)");
function initialize(
string memory name_,
string memory symbol_,
uint256 maxSupply_,
string memory prefix_,
string memory suffix_,
address signer_
) public initializerERC721A initializer {
__Ownable_init();
__Pausable_init();
__EIP712_init("", "");
__ERC721A_init(name_, symbol_);
__AdminManager_init_unchained();
__Supply_init_unchained(maxSupply_);
__UriManager_init_unchained(prefix_, suffix_);
__AdminMint_init_unchained();
_pause();
signer = signer_;
phase = Phase.Presale;
price[Phase.Presale] = 0.089 ether;
price[Phase.SaleOne] = 0.089 ether;
price[Phase.SaleTwo] = 0.089 ether;
presaleCoMuseumLimit = 2;
saleOneCoMuseumLimit = 2;
saleOneAzukiLimit = 2;
saleOneAzukiElementalsLimit = 1;
saleOneAzukiElementalBeanzLimit = 1;
saleOneArcStellarsLimit = 2;
saleTwoAccountLimit = 5;
}
function presale(
uint256[] calldata coMuseumIds_,
uint256[] calldata coMuseumAmounts_,
uint256 accountAmount_,
PresaleRequest calldata request_,
bytes calldata signature_
)
external
payable
whenPresaleAuthorized(accountAmount_, request_, signature_)
whenPhaseIsActive(Phase.Presale)
whenNotPaused
{
uint256 amount = 0;
for (uint256 i = 0; i < coMuseumIds_.length; i++) {
uint256 coMuseumId = coMuseumIds_[i];
uint256 coMuseumAmount = coMuseumAmounts_[i];
_validateCoMuseumOwnership(coMuseumId);
require(
presaleCoMuseumBalances[coMuseumId] + coMuseumAmount <=
presaleCoMuseumLimit,
"Co-Museum exceeds limit"
);
presaleCoMuseumBalances[coMuseumId] += coMuseumAmount;
amount += coMuseumAmount;
}
require(
presaleAccountBalances[msg.sender] + accountAmount_ <=
request_.limit,
"Account exceeds limit"
);
presaleAccountBalances[msg.sender] += accountAmount_;
amount += accountAmount_;
_handlePayment(amount, price[Phase.Presale]);
emit Presale(request_.account, amount);
}
function saleOne(
SaleOneRequest calldata request_
) public payable whenPhaseIsActive(Phase.SaleOne) whenNotPaused {
uint256[] memory coMuseumIds = request_.coMuseumIds;
uint256[] memory coMuseumAmounts = request_.coMuseumAmounts;
uint256[] memory azukiIds = request_.azukiIds;
uint256[] memory azukiAmounts = request_.azukiAmounts;
uint256[] memory azukiElementalsIds = request_.azukiElementalsIds;
uint256[] memory azukiElementalsAmounts = request_
.azukiElementalsAmounts;
uint256[] memory azukiElementalBeanzIds = request_
.azukiElementalBeanzIds;
uint256[] memory azukiElementalBeanzAmounts = request_
.azukiElementalBeanzAmounts;
uint256[] memory arcStellarsIds = request_.arcStellarsIds;
uint256[] memory arcStellarsAmounts = request_.arcStellarsAmounts;
uint256[] memory beanzIds = request_.beanzIds;
uint256[] memory beanzAmounts = request_.beanzAmounts;
uint256 amount = 0;
for (uint256 i = 0; i < coMuseumIds.length; i++) {
uint256 coMuseumId = coMuseumIds[i];
uint256 coMuseumAmount = coMuseumAmounts[i];
_validateCoMuseumOwnership(coMuseumId);
require(
saleOneCoMuseumBalances[coMuseumId] + coMuseumAmount <=
saleOneCoMuseumLimit,
"Co-Museum exceeds limit"
);
saleOneCoMuseumBalances[coMuseumId] += coMuseumAmount;
amount += coMuseumAmount;
}
for (uint256 i = 0; i < azukiIds.length; i++) {
uint256 azukiId = azukiIds[i];
uint256 azukiAmount = azukiAmounts[i];
_validateAzukiOwnership(azukiId);
require(
saleOneAzukiBalances[azukiId] + azukiAmount <=
saleOneAzukiLimit,
"Azuki exceeds limit"
);
saleOneAzukiBalances[azukiId] += azukiAmount;
amount += azukiAmount;
}
for (uint256 i = 0; i < azukiElementalsIds.length; i++) {
uint256 azukiElementalId = azukiElementalsIds[i];
uint256 azukiElementalAmount = azukiElementalsAmounts[i];
_validateAzukiElementalsOwnership(azukiElementalId);
require(
saleOneAzukiElementalsBalances[azukiElementalId] +
azukiElementalAmount <=
saleOneAzukiElementalsLimit,
"Azuki elemental exceeds limit"
);
saleOneAzukiElementalsBalances[
azukiElementalId
] += azukiElementalAmount;
amount += azukiElementalAmount;
}
for (uint256 i = 0; i < azukiElementalBeanzIds.length; i++) {
uint256 azukiElementalBeanzId = azukiElementalBeanzIds[i];
uint256 azukiElementalBeanzAmount = azukiElementalBeanzAmounts[i];
_validateAzukiElementalBeanzOwnership(azukiElementalBeanzId);
require(
saleOneAzukiElementalBeanzBalances[azukiElementalBeanzId] +
azukiElementalBeanzAmount <=
saleOneAzukiElementalBeanzLimit,
"Azuki elemental exceeds limit"
);
saleOneAzukiElementalBeanzBalances[
azukiElementalBeanzId
] += azukiElementalBeanzAmount;
amount += azukiElementalBeanzAmount;
}
for (uint256 i = 0; i < arcStellarsIds.length; i++) {
uint256 arcStellarsId = arcStellarsIds[i];
uint256 arcStellarsAmount = arcStellarsAmounts[i];
_validateArcStellarsOwnership(arcStellarsId);
require(
saleOneArcStellarsBalances[arcStellarsId] + arcStellarsAmount <=
saleOneArcStellarsLimit,
"ARC Stellars exceeds limit"
);
saleOneArcStellarsBalances[arcStellarsId] += arcStellarsAmount;
amount += arcStellarsAmount;
}
for (uint256 i = 0; i < beanzIds.length; i++) {
uint256 beanzId = beanzIds[i];
uint256 beanzAmount = beanzAmounts[i];
_validateBeanzOwnership(beanzId);
require(
saleOneBeanzBalances[beanzId] + beanzAmount <=
saleOneBeanzLimit,
"Beanz exceeds limit"
);
saleOneBeanzBalances[beanzId] += beanzAmount;
amount += beanzAmount;
}
require(reservedAmount + amount <= _maxSupply, "Exceeds supply");
reservedAmount += amount;
_handlePayment(amount, price[Phase.SaleOne]);
emit Presale(msg.sender, amount);
}
function saleTwo(
uint256 amount_
) public payable whenPhaseIsActive(Phase.SaleTwo) whenNotPaused {
require(
saleTwoAccountBalances[msg.sender] + amount_ <= saleTwoAccountLimit,
"Exceeds limit"
);
saleTwoAccountBalances[msg.sender] += amount_;
_handlePayment(amount_, price[Phase.SaleTwo]);
_callMint(msg.sender, amount_);
emit Presale(msg.sender, amount_);
}
function setSigner(address signer_) external onlyOwner {
signer = signer_;
}
function setPhase(Phase phase_) external onlyOwner {
phase = phase_;
}
function setPrice(Phase phase_, uint256 price_) external onlyOwner {
price[phase_] = price_;
}
function adminSetTokensPhase(
SetTokenPhaseRequest calldata request_,
bytes calldata signature_
) external whenSetTokenPhaseAuthorized(request_, signature_) {
uint256[] memory tokenIds = request_.tokenIds;
TokenPhase[] memory phases = request_.phases;
require(tokenIds.length == phases.length, "Invalid request");
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
TokenPhase tokenPhase = phases[i];
tokenPhases[tokenId] = tokenPhase;
emit TokenPhaseChange(tokenId, tokenPhase);
}
}
function lockTokens(uint256[] calldata tokenIds) external {
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
require(msg.sender == ownerOf(tokenId), "Unauthorized request");
tokenPhases[tokenId] = TokenPhase.Claimed;
emit TokenPhaseChange(tokenId, TokenPhase.Claimed);
}
}
function decoupleToken(
DecoupleTokenRequest calldata request_,
bytes calldata signature_
) external whenDecoupleTokenAuthorized(request_, signature_) {
require(
msg.sender == ownerOf(request_.tokenId),
"Unauthorized request"
);
require(
request_.account == ownerOf(request_.tokenId),
"Unauthorized request"
);
tokenPhases[request_.tokenId] = TokenPhase.Decoupled;
emit TokenPhaseChange(request_.tokenId, TokenPhase.Decoupled);
}
function getTokensPhase(
uint256[] calldata tokenIds
) external view returns (uint8[] memory) {
uint8[] memory phases = new uint8[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
phases[i] = uint8(tokenPhases[tokenId]);
}
return phases;
}
function setPresaleCoMuseumLimit(
uint256 presaleCoMuseumLimit_
) external onlyOwner {
presaleCoMuseumLimit = presaleCoMuseumLimit_;
}
function setSaleOneBeanzLimit(
uint256 saleOneBeanzLimit_
) external onlyOwner {
saleOneBeanzLimit = saleOneBeanzLimit_;
}
function setSaleOneCoMuseumLimit(
uint256 saleOneCoMuseumLimit_
) external onlyOwner {
saleOneCoMuseumLimit = saleOneCoMuseumLimit_;
}
function setSaleOneStellarLimit(
uint256 saleOneArcStellarsLimit_
) external onlyOwner {
saleOneArcStellarsLimit = saleOneArcStellarsLimit_;
}
function setSaleOneAzukiLimit(
uint256 saleOneAzukiLimit_
) external onlyOwner {
saleOneAzukiLimit = saleOneAzukiLimit_;
}
function setSaleOneAzukiElementalsLimit(
uint256 saleOneAzukiElementalsLimit_
) external onlyOwner {
saleOneAzukiElementalsLimit = saleOneAzukiElementalsLimit_;
}
function setSaleOneAzukiElementalBeanzLimit(
uint256 saleOneAzukiElementalBeanzLimit_
) external onlyOwner {
saleOneAzukiElementalBeanzLimit = saleOneAzukiElementalBeanzLimit_;
}
function setSaleTwoAccountLimit(
uint256 saleTwoAccountLimit_
) external onlyOwner {
saleTwoAccountLimit = saleTwoAccountLimit_;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function withdraw(address recipient_) external onlyOwner {
(bool success, ) = recipient_.call{value: address(this).balance}("");
require(success, "Withdraw failed");
}
function tokenURI(
uint256 tokenId
) public view override returns (string memory) {
if (!_exists(tokenId)) {
revert URIQueryForNonexistentToken();
}
return _buildUri(tokenId);
}
function _adminMint(address account_, uint256 amount_) internal override {
_callMint(account_, amount_);
}
function _validateCoMuseumOwnership(uint256 id_) private view {
address owner = CO_MUSEUM.ownerOf(id_);
require(
msg.sender == owner ||
DELEGATE_REGISTRY.checkDelegateForERC721(
msg.sender,
owner,
address(CO_MUSEUM),
id_,
""
),
"Invalid Co-Museum owner"
);
}
function _validateAzukiOwnership(uint256 id_) private view {
address owner = AZUKI.ownerOf(id_);
require(
msg.sender == owner ||
DELEGATE_REGISTRY.checkDelegateForERC721(
msg.sender,
owner,
address(AZUKI),
id_,
""
),
"Invalid Azuki owner"
);
}
function _validateBeanzOwnership(uint256 id_) private view {
address owner = AZUKI_BEANZ.ownerOf(id_);
require(
msg.sender == owner ||
DELEGATE_REGISTRY.checkDelegateForERC721(
msg.sender,
owner,
address(AZUKI_BEANZ),
id_,
""
),
"Invalid Beanz owner"
);
}
function _validateAzukiElementalsOwnership(uint256 id_) private view {
address owner = AZUKI_ELEMENTALS.ownerOf(id_);
require(
msg.sender == owner ||
DELEGATE_REGISTRY.checkDelegateForERC721(
msg.sender,
owner,
address(AZUKI_ELEMENTALS),
id_,
""
),
"Invalid Azuki elementals owner"
);
}
function _validateAzukiElementalBeanzOwnership(uint256 id_) private view {
address owner = AZUKI_ELEMENTAL_BEANZ.ownerOf(id_);
require(
msg.sender == owner ||
DELEGATE_REGISTRY.checkDelegateForERC721(
msg.sender,
owner,
address(AZUKI_ELEMENTAL_BEANZ),
id_,
""
),
"Invalid Azuki elemental beanz owner"
);
}
function _validateArcStellarsOwnership(uint256 id_) private view {
address owner = ARC_STELLARS.ownerOf(id_);
require(
msg.sender == owner ||
DELEGATE_REGISTRY.checkDelegateForERC721(
msg.sender,
owner,
address(ARC_STELLARS),
id_,
""
),
"Invalid ARC Stellars owner"
);
}
function _handlePayment(uint256 amount_, uint256 price_) internal {
uint256 total = amount_ * price_;
require(msg.value >= total, "Not enough ETH");
if (msg.value > total) {
payable(msg.sender).transfer(msg.value - total);
}
}
function _callMint(
address account_,
uint256 amount_
) internal onlyInSupply(amount_) {
require(tx.origin == msg.sender, "No bots");
_safeMint(account_, amount_);
}
function _currentSupply() internal view override returns (uint256) {
return totalSupply();
}
function _hashPresaleTypedData(
PresaleRequest calldata request_
) internal pure returns (bytes32) {
return
keccak256(
abi.encode(
PRESALE_REQUEST_TYPE_HASH,
request_.account,
request_.limit
)
);
}
function _hashSetTokenPhaseTypedData(
SetTokenPhaseRequest calldata request_
) internal pure returns (bytes32) {
return
keccak256(
abi.encode(
SET_TOKEN_PHASE_REQUEST_TYPE_HASH,
keccak256(abi.encodePacked(request_.tokenIds)),
keccak256(
abi.encodePacked(_convertPhasesToUint8(request_.phases))
)
)
);
}
function _hashDecoupleTokenTypedData(
DecoupleTokenRequest calldata request_
) internal pure returns (bytes32) {
return
keccak256(
abi.encode(
DECOUPLE_TOKEN_PHASE_REQUEST_TYPE_HASH,
request_.account,
request_.tokenId
)
);
}
function _convertPhasesToUint8(
TokenPhase[] memory phases
) internal pure returns (uint8[] memory) {
uint8[] memory uint8Phases = new uint8[](phases.length);
for (uint i = 0; i < phases.length; i++) {
uint8Phases[i] = uint8(phases[i]);
}
return uint8Phases;
}
function _beforeTokenTransfers(
address from_,
address to_,
uint256 tokenId_,
uint256 quantity_
) internal override {
if (!allowedTransfers[tokenId_]) {
require(
from_ == address(0) ||
tokenPhases[tokenId_] != TokenPhase.Claimed,
"Token not transferable"
);
}
super._beforeTokenTransfers(from_, to_, tokenId_, quantity_);
}
function setReservedAmount(uint256 reservedAmount_) external onlyOwner {
reservedAmount = reservedAmount_;
}
function _startTokenId() internal pure override returns (uint256) {
return 1;
}
function _EIP712Name() internal pure override returns (string memory) {
return "AZUKI_X_CO_MUSEUM";
}
function _EIP712Version() internal pure override returns (string memory) {
return "0.1.0";
}
function isApprovedForAll(
address owner,
address operator
) public view virtual override returns (bool) {
return isAdmin(operator) || super.isApprovedForAll(owner, operator);
}
function allowTokenTransfer(
uint256 tokenId,
bool allow
) external onlyAdmin {
allowedTransfers[tokenId] = allow;
}
modifier whenPresaleAuthorized(
uint256 amount_,
PresaleRequest calldata request_,
bytes calldata signature_
) {
if (amount_ > 0) {
bytes32 structHash = _hashPresaleTypedData(request_);
bytes32 digest = _hashTypedDataV4(structHash);
address recoveredSigner = ECDSAUpgradeable.recover(
digest,
signature_
);
require(recoveredSigner == signer, "Unauthorized request");
require(request_.account == msg.sender, "Invalid account");
}
_;
}
modifier whenSetTokenPhaseAuthorized(
SetTokenPhaseRequest calldata request_,
bytes calldata signature_
) {
bytes32 structHash = _hashSetTokenPhaseTypedData(request_);
bytes32 digest = _hashTypedDataV4(structHash);
address recoveredSigner = ECDSAUpgradeable.recover(digest, signature_);
require(recoveredSigner == signer, "Unauthorized request");
_;
}
modifier whenPhaseIsActive(Phase phase_) {
require(phase == phase_, "Phase not enabled");
_;
}
modifier whenDecoupleTokenAuthorized(
DecoupleTokenRequest calldata request_,
bytes calldata signature_
) {
bytes32 structHash = _hashDecoupleTokenTypedData(request_);
bytes32 digest = _hashTypedDataV4(structHash);
address recoveredSigner = ECDSAUpgradeable.recover(digest, signature_);
require(recoveredSigner == signer, "Unauthorized request");
require(tx.origin == request_.account, "Not bots allowed");
_;
}
}
SupplyUpgradable.sol 38 lines
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./AdminManagerUpgradable.sol";
abstract contract SupplyUpgradable is Initializable, AdminManagerUpgradable {
uint256 internal _maxSupply;
function __Supply_init(uint256 maxSupply_) internal onlyInitializing {
__AdminManager_init_unchained();
__Supply_init_unchained(maxSupply_);
}
function __Supply_init_unchained(
uint256 maxSupply_
) internal onlyInitializing {
_maxSupply = maxSupply_;
}
function setMaxSupply(uint256 maxSupply_) external onlyAdmin {
_maxSupply = maxSupply_;
}
function maxSupply() external view returns (uint256) {
return _maxSupply;
}
function _currentSupply() internal view virtual returns (uint256);
modifier onlyInSupply(uint256 amount_) {
require(_currentSupply() + amount_ <= _maxSupply, "Exceeds supply");
_;
}
uint256[49] private __gap;
}
UriManagerUpgradable.sol 52 lines
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol";
import "./AdminManagerUpgradable.sol";
contract UriManagerUpgradable is Initializable, AdminManagerUpgradable {
using StringsUpgradeable for uint256;
string internal _prefix;
string internal _suffix;
function prefix() public view returns (string memory) {
return _prefix;
}
function suffix() public view returns (string memory) {
return _suffix;
}
function __UriManager_init(
string memory prefix_,
string memory suffix_
) internal onlyInitializing {
__AdminManager_init_unchained();
__UriManager_init_unchained(prefix_, suffix_);
}
function __UriManager_init_unchained(
string memory prefix_,
string memory suffix_
) internal onlyInitializing {
_prefix = prefix_;
_suffix = suffix_;
}
function _buildUri(uint256 tokenId) internal view returns (string memory) {
return string(abi.encodePacked(_prefix, tokenId.toString(), _suffix));
}
function setPrefix(string calldata prefix_) external onlyAdmin {
_prefix = prefix_;
}
function setSuffix(string calldata suffix_) external onlyAdmin {
_suffix = suffix_;
}
uint256[48] private __gap;
}
ERC721A__Initializable.sol 75 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base contract to aid in writing upgradeable diamond facet contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
import {ERC721A__InitializableStorage} from './ERC721A__InitializableStorage.sol';
abstract contract ERC721A__Initializable {
using ERC721A__InitializableStorage for ERC721A__InitializableStorage.Layout;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializerERC721A() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(
ERC721A__InitializableStorage.layout()._initializing
? _isConstructor()
: !ERC721A__InitializableStorage.layout()._initialized,
'ERC721A__Initializable: contract is already initialized'
);
bool isTopLevelCall = !ERC721A__InitializableStorage.layout()._initializing;
if (isTopLevelCall) {
ERC721A__InitializableStorage.layout()._initializing = true;
ERC721A__InitializableStorage.layout()._initialized = true;
}
_;
if (isTopLevelCall) {
ERC721A__InitializableStorage.layout()._initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializingERC721A() {
require(
ERC721A__InitializableStorage.layout()._initializing,
'ERC721A__Initializable: contract is not initializing'
);
_;
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly {
cs := extcodesize(self)
}
return cs == 0;
}
}
ERC721A__InitializableStorage.sol 29 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This is a base storage for the initialization function for upgradeable diamond facet contracts
**/
library ERC721A__InitializableStorage {
struct Layout {
/*
* Indicates that the contract has been initialized.
*/
bool _initialized;
/*
* Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.initializable.facet');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}
ERC721AStorage.sol 60 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library ERC721AStorage {
// Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).
struct TokenApprovalRef {
address value;
}
struct Layout {
// =============================================================
// STORAGE
// =============================================================
// The next token ID to be minted.
uint256 _currentIndex;
// The number of tokens burned.
uint256 _burnCounter;
// Token name
string _name;
// Token symbol
string _symbol;
// Mapping from token ID to ownership details
// An empty struct value does not necessarily mean the token is unowned.
// See {_packedOwnershipOf} implementation for details.
//
// Bits Layout:
// - [0..159] `addr`
// - [160..223] `startTimestamp`
// - [224] `burned`
// - [225] `nextInitialized`
// - [232..255] `extraData`
mapping(uint256 => uint256) _packedOwnerships;
// Mapping owner address to address data.
//
// Bits Layout:
// - [0..63] `balance`
// - [64..127] `numberMinted`
// - [128..191] `numberBurned`
// - [192..255] `aux`
mapping(address => uint256) _packedAddressData;
// Mapping from token ID to approved address.
mapping(uint256 => ERC721AStorage.TokenApprovalRef) _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) _operatorApprovals;
// The amount of tokens minted above `_sequentialUpTo()`.
// We call these spot mints (i.e. non-sequential mints).
uint256 _spotMinted;
}
bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.ERC721A');
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}
ERC721AUpgradeable.sol 1273 lines
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs
pragma solidity ^0.8.4;
import './IERC721AUpgradeable.sol';
import {ERC721AStorage} from './ERC721AStorage.sol';
import './ERC721A__Initializable.sol';
/**
* @dev Interface of ERC721 token receiver.
*/
interface ERC721A__IERC721ReceiverUpgradeable {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
/**
* @title ERC721A
*
* @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
* Non-Fungible Token Standard, including the Metadata extension.
* Optimized for lower gas during batch mints.
*
* Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
* starting from `_startTokenId()`.
*
* The `_sequentialUpTo()` function can be overriden to enable spot mints
* (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`.
*
* Assumptions:
*
* - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
* - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
*/
contract ERC721AUpgradeable is ERC721A__Initializable, IERC721AUpgradeable {
using ERC721AStorage for ERC721AStorage.Layout;
// =============================================================
// CONSTANTS
// =============================================================
// Mask of an entry in packed address data.
uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1;
// The bit position of `numberMinted` in packed address data.
uint256 private constant _BITPOS_NUMBER_MINTED = 64;
// The bit position of `numberBurned` in packed address data.
uint256 private constant _BITPOS_NUMBER_BURNED = 128;
// The bit position of `aux` in packed address data.
uint256 private constant _BITPOS_AUX = 192;
// Mask of all 256 bits in packed address data except the 64 bits for `aux`.
uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1;
// The bit position of `startTimestamp` in packed ownership.
uint256 private constant _BITPOS_START_TIMESTAMP = 160;
// The bit mask of the `burned` bit in packed ownership.
uint256 private constant _BITMASK_BURNED = 1 << 224;
// The bit position of the `nextInitialized` bit in packed ownership.
uint256 private constant _BITPOS_NEXT_INITIALIZED = 225;
// The bit mask of the `nextInitialized` bit in packed ownership.
uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225;
// The bit position of `extraData` in packed ownership.
uint256 private constant _BITPOS_EXTRA_DATA = 232;
// Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.
uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1;
// The mask of the lower 160 bits for addresses.
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
// The maximum `quantity` that can be minted with {_mintERC2309}.
// This limit is to prevent overflows on the address data entries.
// For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}
// is required to cause an overflow, which is unrealistic.
uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000;
// The `Transfer` event signature is given by:
// `keccak256(bytes("Transfer(address,address,uint256)"))`.
bytes32 private constant _TRANSFER_EVENT_SIGNATURE =
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
// =============================================================
// CONSTRUCTOR
// =============================================================
function __ERC721A_init(string memory name_, string memory symbol_) internal onlyInitializingERC721A {
__ERC721A_init_unchained(name_, symbol_);
}
function __ERC721A_init_unchained(string memory name_, string memory symbol_) internal onlyInitializingERC721A {
ERC721AStorage.layout()._name = name_;
ERC721AStorage.layout()._symbol = symbol_;
ERC721AStorage.layout()._currentIndex = _startTokenId();
if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector);
}
// =============================================================
// TOKEN COUNTING OPERATIONS
// =============================================================
/**
* @dev Returns the starting token ID for sequential mints.
*
* Override this function to change the starting token ID for sequential mints.
*
* Note: The value returned must never change after any tokens have been minted.
*/
function _startTokenId() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev Returns the maximum token ID (inclusive) for sequential mints.
*
* Override this function to return a value less than 2**256 - 1,
* but greater than `_startTokenId()`, to enable spot (non-sequential) mints.
*
* Note: The value returned must never change after any tokens have been minted.
*/
function _sequentialUpTo() internal view virtual returns (uint256) {
return type(uint256).max;
}
/**
* @dev Returns the next token ID to be minted.
*/
function _nextTokenId() internal view virtual returns (uint256) {
return ERC721AStorage.layout()._currentIndex;
}
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() public view virtual override returns (uint256 result) {
// Counter underflow is impossible as `_burnCounter` cannot be incremented
// more than `_currentIndex + _spotMinted - _startTokenId()` times.
unchecked {
// With spot minting, the intermediate `result` can be temporarily negative,
// and the computation must be unchecked.
result = ERC721AStorage.layout()._currentIndex - ERC721AStorage.layout()._burnCounter - _startTokenId();
if (_sequentialUpTo() != type(uint256).max) result += ERC721AStorage.layout()._spotMinted;
}
}
/**
* @dev Returns the total amount of tokens minted in the contract.
*/
function _totalMinted() internal view virtual returns (uint256 result) {
// Counter underflow is impossible as `_currentIndex` does not decrement,
// and it is initialized to `_startTokenId()`.
unchecked {
result = ERC721AStorage.layout()._currentIndex - _startTokenId();
if (_sequentialUpTo() != type(uint256).max) result += ERC721AStorage.layout()._spotMinted;
}
}
/**
* @dev Returns the total number of tokens burned.
*/
function _totalBurned() internal view virtual returns (uint256) {
return ERC721AStorage.layout()._burnCounter;
}
/**
* @dev Returns the total number of tokens that are spot-minted.
*/
function _totalSpotMinted() internal view virtual returns (uint256) {
return ERC721AStorage.layout()._spotMinted;
}
// =============================================================
// ADDRESS DATA OPERATIONS
// =============================================================
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector);
return ERC721AStorage.layout()._packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens minted by `owner`.
*/
function _numberMinted(address owner) internal view returns (uint256) {
return
(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens burned by or on behalf of `owner`.
*/
function _numberBurned(address owner) internal view returns (uint256) {
return
(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
*/
function _getAux(address owner) internal view returns (uint64) {
return uint64(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_AUX);
}
/**
* Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
* If there are multiple variables, please pack them into a uint64.
*/
function _setAux(address owner, uint64 aux) internal virtual {
uint256 packed = ERC721AStorage.layout()._packedAddressData[owner];
uint256 auxCasted;
// Cast `aux` with assembly to avoid redundant masking.
assembly {
auxCasted := aux
}
packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
ERC721AStorage.layout()._packedAddressData[owner] = packed;
}
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
// The interface IDs are constants representing the first 4 bytes
// of the XOR of all function selectors in the interface.
// See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)
// (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)
return
interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165.
interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721.
interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
}
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() public view virtual override returns (string memory) {
return ERC721AStorage.layout()._name;
}
/**
* @dev Returns the token collection symbol.
*/
function symbol() public view virtual override returns (string memory) {
return ERC721AStorage.layout()._symbol;
}
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector);
string memory baseURI = _baseURI();
return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
}
/**
* @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, it can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return '';
}
// =============================================================
// OWNERSHIPS OPERATIONS
// =============================================================
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
return address(uint160(_packedOwnershipOf(tokenId)));
}
/**
* @dev Gas spent here starts off proportional to the maximum mint batch size.
* It gradually moves to O(1) as tokens get transferred around over time.
*/
function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnershipOf(tokenId));
}
/**
* @dev Returns the unpacked `TokenOwnership` struct at `index`.
*/
function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) {
return _unpackedOwnership(ERC721AStorage.layout()._packedOwnerships[index]);
}
/**
* @dev Returns whether the ownership slot at `index` is initialized.
* An uninitialized slot does not necessarily mean that the slot has no owner.
*/
function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) {
return ERC721AStorage.layout()._packedOwnerships[index] != 0;
}
/**
* @dev Initializes the ownership slot minted at `index` for efficiency purposes.
*/
function _initializeOwnershipAt(uint256 index) internal virtual {
if (ERC721AStorage.layout()._packedOwnerships[index] == 0) {
ERC721AStorage.layout()._packedOwnerships[index] = _packedOwnershipOf(index);
}
}
/**
* @dev Returns the packed ownership data of `tokenId`.
*/
function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) {
if (_startTokenId() <= tokenId) {
packed = ERC721AStorage.layout()._packedOwnerships[tokenId];
if (tokenId > _sequentialUpTo()) {
if (_packedOwnershipExists(packed)) return packed;
_revert(OwnerQueryForNonexistentToken.selector);
}
// If the data at the starting slot does not exist, start the scan.
if (packed == 0) {
if (tokenId >= ERC721AStorage.layout()._currentIndex) _revert(OwnerQueryForNonexistentToken.selector);
// Invariant:
// There will always be an initialized ownership slot
// (i.e. `ownership.addr != address(0) && ownership.burned == false`)
// before an unintialized ownership slot
// (i.e. `ownership.addr == address(0) && ownership.burned == false`)
// Hence, `tokenId` will not underflow.
//
// We can directly compare the packed value.
// If the address is zero, packed will be zero.
for (;;) {
unchecked {
packed = ERC721AStorage.layout()._packedOwnerships[--tokenId];
}
if (packed == 0) continue;
if (packed & _BITMASK_BURNED == 0) return packed;
// Otherwise, the token is burned, and we must revert.
// This handles the case of batch burned tokens, where only the burned bit
// of the starting slot is set, and remaining slots are left uninitialized.
_revert(OwnerQueryForNonexistentToken.selector);
}
}
// Otherwise, the data exists and we can skip the scan.
// This is possible because we have already achieved the target condition.
// This saves 2143 gas on transfers of initialized tokens.
// If the token is not burned, return `packed`. Otherwise, revert.
if (packed & _BITMASK_BURNED == 0) return packed;
}
_revert(OwnerQueryForNonexistentToken.selector);
}
/**
* @dev Returns the unpacked `TokenOwnership` struct from `packed`.
*/
function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) {
ownership.addr = address(uint160(packed));
ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP);
ownership.burned = packed & _BITMASK_BURNED != 0;
ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA);
}
/**
* @dev Packs ownership data into a single uint256.
*/
function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner := and(owner, _BITMASK_ADDRESS)
// `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
}
}
/**
* @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
*/
function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) {
// For branchless setting of the `nextInitialized` flag.
assembly {
// `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
}
}
// =============================================================
// APPROVAL OPERATIONS
// =============================================================
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
*/
function approve(address to, uint256 tokenId) public payable virtual override {
_approve(to, tokenId, true);
}
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector);
return ERC721AStorage.layout()._tokenApprovals[tokenId].value;
}
/**
* @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) public virtual override {
ERC721AStorage.layout()._operatorApprovals[_msgSenderERC721A()][operator] = approved;
emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
}
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return ERC721AStorage.layout()._operatorApprovals[owner][operator];
}
/**
* @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. See {_mint}.
*/
function _exists(uint256 tokenId) internal view virtual returns (bool result) {
if (_startTokenId() <= tokenId) {
if (tokenId > _sequentialUpTo())
return _packedOwnershipExists(ERC721AStorage.layout()._packedOwnerships[tokenId]);
if (tokenId < ERC721AStorage.layout()._currentIndex) {
uint256 packed;
while ((packed = ERC721AStorage.layout()._packedOwnerships[tokenId]) == 0) --tokenId;
result = packed & _BITMASK_BURNED == 0;
}
}
}
/**
* @dev Returns whether `packed` represents a token that exists.
*/
function _packedOwnershipExists(uint256 packed) private pure returns (bool result) {
assembly {
// The following is equivalent to `owner != address(0) && burned == false`.
// Symbolically tested.
result := gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED))
}
}
/**
* @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
*/
function _isSenderApprovedOrOwner(
address approvedAddress,
address owner,
address msgSender
) private pure returns (bool result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner := and(owner, _BITMASK_ADDRESS)
// Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
msgSender := and(msgSender, _BITMASK_ADDRESS)
// `msgSender == owner || msgSender == approvedAddress`.
result := or(eq(msgSender, owner), eq(msgSender, approvedAddress))
}
}
/**
* @dev Returns the storage slot and value for the approved address of `tokenId`.
*/
function _getApprovedSlotAndAddress(uint256 tokenId)
private
view
returns (uint256 approvedAddressSlot, address approvedAddress)
{
ERC721AStorage.TokenApprovalRef storage tokenApproval = ERC721AStorage.layout()._tokenApprovals[tokenId];
// The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.
assembly {
approvedAddressSlot := tokenApproval.slot
approvedAddress := sload(approvedAddressSlot)
}
}
// =============================================================
// TRANSFER OPERATIONS
// =============================================================
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* 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
) public payable virtual override {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
// Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean.
from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS));
if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector);
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
// The nested ifs save around 20+ gas over a compound boolean condition.
if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
_beforeTokenTransfers(from, to, tokenId, 1);
// Clear approvals from the previous owner.
assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.
sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
unchecked {
// We can directly increment and decrement the balances.
--ERC721AStorage.layout()._packedAddressData[from]; // Updates: `balance -= 1`.
++ERC721AStorage.layout()._packedAddressData[to]; // Updates: `balance += 1`.
// Updates:
// - `address` to the next owner.
// - `startTimestamp` to the timestamp of transfering.
// - `burned` to `false`.
// - `nextInitialized` to `true`.
ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(
to,
_BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).
if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) {
// If the next slot is within bounds.
if (nextTokenId != ERC721AStorage.layout()._currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
assembly {
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
from, // `from`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
if (toMasked == 0) _revert(TransferToZeroAddress.selector);
_afterTokenTransfers(from, to, tokenId, 1);
}
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public payable virtual override {
safeTransferFrom(from, to, tokenId, '');
}
/**
* @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 memory _data
) public payable virtual override {
transferFrom(from, to, tokenId);
if (to.code.length != 0)
if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
}
/**
* @dev Hook that is called before a set of serially-ordered token IDs
* are about to be transferred. This includes minting.
* And also called before burning one token.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* 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, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/
function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
/**
* @dev Hook that is called after a set of serially-ordered token IDs
* have been transferred. This includes minting.
* And also called after one token has been burned.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
* transferred to `to`.
* - When `from` is zero, `tokenId` has been minted for `to`.
* - When `to` is zero, `tokenId` has been burned by `from`.
* - `from` and `to` are never both zero.
*/
function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity
) internal virtual {}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
*
* `from` - Previous owner of the given token ID.
* `to` - Target address that will receive the token.
* `tokenId` - Token ID to be transferred.
* `_data` - Optional data to send along with the call.
*
* Returns whether the call correctly returned the expected magic value.
*/
function _checkContractOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
try
ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data)
returns (bytes4 retval) {
return retval == ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
assembly {
revert(add(32, reason), mload(reason))
}
}
}
// =============================================================
// MINT OPERATIONS
// =============================================================
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {Transfer} event for each mint.
*/
function _mint(address to, uint256 quantity) internal virtual {
uint256 startTokenId = ERC721AStorage.layout()._currentIndex;
if (quantity == 0) _revert(MintZeroQuantity.selector);
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are incredibly unrealistic.
// `balance` and `numberMinted` have a maximum limit of 2**64.
// `tokenId` has a maximum limit of 2**256.
unchecked {
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `quantity == 1`.
ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
// Updates:
// - `balance += quantity`.
// - `numberMinted += quantity`.
//
// We can directly add to the `balance` and `numberMinted`.
ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
if (toMasked == 0) _revert(MintToZeroAddress.selector);
uint256 end = startTokenId + quantity;
uint256 tokenId = startTokenId;
if (end - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);
do {
assembly {
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
0, // `address(0)`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
// The `!=` check ensures that large values of `quantity`
// that overflows uint256 will make the loop run out of gas.
} while (++tokenId != end);
ERC721AStorage.layout()._currentIndex = end;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* This function is intended for efficient minting only during contract creation.
*
* It emits only one {ConsecutiveTransfer} as defined in
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
* instead of a sequence of {Transfer} event(s).
*
* Calling this function outside of contract creation WILL make your contract
* non-compliant with the ERC721 standard.
* For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
* {ConsecutiveTransfer} event is only permissible during contract creation.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {ConsecutiveTransfer} event.
*/
function _mintERC2309(address to, uint256 quantity) internal virtual {
uint256 startTokenId = ERC721AStorage.layout()._currentIndex;
if (to == address(0)) _revert(MintToZeroAddress.selector);
if (quantity == 0) _revert(MintZeroQuantity.selector);
if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector);
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are unrealistic due to the above check for `quantity` to be below the limit.
unchecked {
// Updates:
// - `balance += quantity`.
// - `numberMinted += quantity`.
//
// We can directly add to the `balance` and `numberMinted`.
ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1);
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `quantity == 1`.
ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
if (startTokenId + quantity - 1 > _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);
emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to);
ERC721AStorage.layout()._currentIndex = startTokenId + quantity;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Safely mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
* - `quantity` must be greater than 0.
*
* See {_mint}.
*
* Emits a {Transfer} event for each mint.
*/
function _safeMint(
address to,
uint256 quantity,
bytes memory _data
) internal virtual {
_mint(to, quantity);
unchecked {
if (to.code.length != 0) {
uint256 end = ERC721AStorage.layout()._currentIndex;
uint256 index = end - quantity;
do {
if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
} while (index < end);
// This prevents reentrancy to `_safeMint`.
// It does not prevent reentrancy to `_safeMintSpot`.
if (ERC721AStorage.layout()._currentIndex != end) revert();
}
}
}
/**
* @dev Equivalent to `_safeMint(to, quantity, '')`.
*/
function _safeMint(address to, uint256 quantity) internal virtual {
_safeMint(to, quantity, '');
}
/**
* @dev Mints a single token at `tokenId`.
*
* Note: A spot-minted `tokenId` that has been burned can be re-minted again.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` must be greater than `_sequentialUpTo()`.
* - `tokenId` must not exist.
*
* Emits a {Transfer} event for each mint.
*/
function _mintSpot(address to, uint256 tokenId) internal virtual {
if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector);
uint256 prevOwnershipPacked = ERC721AStorage.layout()._packedOwnerships[tokenId];
if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector);
_beforeTokenTransfers(address(0), to, tokenId, 1);
// Overflows are incredibly unrealistic.
// The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1.
// `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1.
unchecked {
// Updates:
// - `address` to the owner.
// - `startTimestamp` to the timestamp of minting.
// - `burned` to `false`.
// - `nextInitialized` to `true` (as `quantity == 1`).
ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(
to,
_nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked)
);
// Updates:
// - `balance += 1`.
// - `numberMinted += 1`.
//
// We can directly add to the `balance` and `numberMinted`.
ERC721AStorage.layout()._packedAddressData[to] += (1 << _BITPOS_NUMBER_MINTED) | 1;
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.
uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS;
if (toMasked == 0) _revert(MintToZeroAddress.selector);
assembly {
// Emit the `Transfer` event.
log4(
0, // Start of data (0, since no data).
0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
0, // `address(0)`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
++ERC721AStorage.layout()._spotMinted;
}
_afterTokenTransfers(address(0), to, tokenId, 1);
}
/**
* @dev Safely mints a single token at `tokenId`.
*
* Note: A spot-minted `tokenId` that has been burned can be re-minted again.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}.
* - `tokenId` must be greater than `_sequentialUpTo()`.
* - `tokenId` must not exist.
*
* See {_mintSpot}.
*
* Emits a {Transfer} event.
*/
function _safeMintSpot(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mintSpot(to, tokenId);
unchecked {
if (to.code.length != 0) {
uint256 currentSpotMinted = ERC721AStorage.layout()._spotMinted;
if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
// This prevents reentrancy to `_safeMintSpot`.
// It does not prevent reentrancy to `_safeMint`.
if (ERC721AStorage.layout()._spotMinted != currentSpotMinted) revert();
}
}
}
/**
* @dev Equivalent to `_safeMintSpot(to, tokenId, '')`.
*/
function _safeMintSpot(address to, uint256 tokenId) internal virtual {
_safeMintSpot(to, tokenId, '');
}
// =============================================================
// APPROVAL OPERATIONS
// =============================================================
/**
* @dev Equivalent to `_approve(to, tokenId, false)`.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_approve(to, tokenId, false);
}
/**
* @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:
*
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function _approve(
address to,
uint256 tokenId,
bool approvalCheck
) internal virtual {
address owner = ownerOf(tokenId);
if (approvalCheck && _msgSenderERC721A() != owner)
if (!isApprovedForAll(owner, _msgSenderERC721A())) {
_revert(ApprovalCallerNotOwnerNorApproved.selector);
}
ERC721AStorage.layout()._tokenApprovals[tokenId].value = to;
emit Approval(owner, to, tokenId);
}
// =============================================================
// BURN OPERATIONS
// =============================================================
/**
* @dev Equivalent to `_burn(tokenId, false)`.
*/
function _burn(uint256 tokenId) internal virtual {
_burn(tokenId, false);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId, bool approvalCheck) internal virtual {
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
address from = address(uint160(prevOwnershipPacked));
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
if (approvalCheck) {
// The nested ifs save around 20+ gas over a compound boolean condition.
if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
}
_beforeTokenTransfers(from, address(0), tokenId, 1);
// Clear approvals from the previous owner.
assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.
sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for
// ownership above and the recipient's balance can't realistically overflow.
// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.
unchecked {
// Updates:
// - `balance -= 1`.
// - `numberBurned += 1`.
//
// We can directly decrement the balance, and increment the number burned.
// This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
ERC721AStorage.layout()._packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1;
// Updates:
// - `address` to the last owner.
// - `startTimestamp` to the timestamp of burning.
// - `burned` to `true`.
// - `nextInitialized` to `true`.
ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData(
from,
(_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .
if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) {
uint256 nextTokenId = tokenId + 1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).
if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) {
// If the next slot is within bounds.
if (nextTokenId != ERC721AStorage.layout()._currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, address(0), tokenId);
_afterTokenTransfers(from, address(0), tokenId, 1);
// Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times.
unchecked {
ERC721AStorage.layout()._burnCounter++;
}
}
// =============================================================
// EXTRA DATA OPERATIONS
// =============================================================
/**
* @dev Directly sets the extra data for the ownership data `index`.
*/
function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual {
uint256 packed = ERC721AStorage.layout()._packedOwnerships[index];
if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector);
uint256 extraDataCasted;
// Cast `extraData` with assembly to avoid redundant masking.
assembly {
extraDataCasted := extraData
}
packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
ERC721AStorage.layout()._packedOwnerships[index] = packed;
}
/**
* @dev Called during each token transfer to set the 24bit `extraData` field.
* Intended to be overridden by the cosumer contract.
*
* `previousExtraData` - the value of `extraData` before transfer.
*
* 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, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/
function _extraData(
address from,
address to,
uint24 previousExtraData
) internal view virtual returns (uint24) {}
/**
* @dev Returns the next extra data for the packed ownership data.
* The returned result is shifted into position.
*/
function _nextExtraData(
address from,
address to,
uint256 prevOwnershipPacked
) private view returns (uint256) {
uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
}
// =============================================================
// OTHER OPERATIONS
// =============================================================
/**
* @dev Returns the message sender (defaults to `msg.sender`).
*
* If you are writing GSN compatible contracts, you need to override this function.
*/
function _msgSenderERC721A() internal view virtual returns (address) {
return msg.sender;
}
/**
* @dev Converts a uint256 to its ASCII string decimal representation.
*/
function _toString(uint256 value) internal pure virtual returns (string memory str) {
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but
// we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.
// We will need 1 word for the trailing zeros padding, 1 word for the length,
// and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.
let m := add(mload(0x40), 0xa0)
// Update the free memory pointer to allocate.
mstore(0x40, m)
// Assign the `str` to the end.
str := sub(m, 0x20)
// Zeroize the slot after the string.
mstore(str, 0)
// Cache the end of the memory to calculate the length later.
let end := str
// We write the string from rightmost digit to leftmost digit.
// The following is essentially a do-while loop that also handles the zero case.
// prettier-ignore
for { let temp := value } 1 {} {
str := sub(str, 1)
// Write the character to the pointer.
// The ASCII index of the '0' character is 48.
mstore8(str, add(48, mod(temp, 10)))
// Keep dividing `temp` until zero.
temp := div(temp, 10)
// prettier-ignore
if iszero(temp) { break }
}
let length := sub(end, str)
// Move the pointer 32 bytes leftwards to make room for the length.
str := sub(str, 0x20)
// Store the length.
mstore(str, le...
// [truncated — 50246 bytes total]
IERC721AUpgradeable.sol 307 lines
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.3.0
// Creator: Chiru Labs
pragma solidity ^0.8.4;
/**
* @dev Interface of ERC721A.
*/
interface IERC721AUpgradeable {
/**
* The caller must own the token or be an approved operator.
*/
error ApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/
error ApprovalQueryForNonexistentToken();
/**
* Cannot query the balance for the zero address.
*/
error BalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/
error MintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/
error MintZeroQuantity();
/**
* The token does not exist.
*/
error OwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/
error TransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/
error TransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/
error TransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/
error TransferToZeroAddress();
/**
* The token does not exist.
*/
error URIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/
error MintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/
error OwnershipNotInitializedForExtraData();
/**
* `_sequentialUpTo()` must be greater than `_startTokenId()`.
*/
error SequentialUpToTooSmall();
/**
* The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`.
*/
error SequentialMintExceedsLimit();
/**
* Spot minting requires a `tokenId` greater than `_sequentialUpTo()`.
*/
error SpotMintTokenIdTooSmall();
/**
* Cannot mint over a token that already exists.
*/
error TokenAlreadyExists();
/**
* The feature is not compatible with spot mints.
*/
error NotCompatibleWithSpotMints();
// =============================================================
// STRUCTS
// =============================================================
struct TokenOwnership {
// The address of the owner.
address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.
uint64 startTimestamp;
// Whether the token has been burned.
bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
uint24 extraData;
}
// =============================================================
// TOKEN COUNTERS
// =============================================================
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() external view returns (uint256);
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
// =============================================================
// IERC721
// =============================================================
/**
* @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,
bytes calldata data
) external payable;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Transfers `tokenId` 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 payable;
/**
* @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 payable;
/**
* @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 the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @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);
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @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);
// =============================================================
// IERC2309
// =============================================================
/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}
Read Contract
ARC_STELLARS 0xb2caf790 → address
AZUKI 0xd2c8ed4c → address
AZUKI_BEANZ 0xcc5dbcf2 → address
AZUKI_ELEMENTALS 0x3d8f833d → address
AZUKI_ELEMENTAL_BEANZ 0x98ac859e → address
CO_MUSEUM 0x096cca7d → address
DELEGATE_REGISTRY 0x8286eee2 → address
allowedTransfers 0x3886d512 → bool
balanceOf 0x70a08231 → uint256
claimNonces 0xdb6c7d3e → uint256
eip712Domain 0x84b0196e → bytes1, string, string, uint256, address, bytes32, uint256[]
getApproved 0x081812fc → address
getTokensPhase 0xd454e0b3 → uint8[]
isAdmin 0x24d7806c → bool
isApprovedForAll 0xe985e9c5 → bool
maxSupply 0xd5abeb01 → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
paused 0x5c975abb → bool
phase 0xb1c9fe6e → uint8
prefix 0x75dadb32 → string
presaleAccountBalances 0x3c80c1d1 → uint256
presaleCoMuseumBalances 0x9831ef2a → uint256
presaleCoMuseumLimit 0x1429fbe4 → uint256
price 0xb7fafcd7 → uint256
reservedAmount 0xf92c45b7 → uint256
saleOneArcStellarsBalances 0xbde750fb → uint256
saleOneArcStellarsLimit 0x8e8a07b3 → uint256
saleOneAzukiBalances 0x4bf47ebd → uint256
saleOneAzukiElementalBeanzBalances 0xff1473a8 → uint256
saleOneAzukiElementalBeanzLimit 0x782312a3 → uint256
saleOneAzukiElementalsBalances 0x6e820527 → uint256
saleOneAzukiElementalsLimit 0xe7ebdca6 → uint256
saleOneAzukiLimit 0x481b86ac → uint256
saleOneBeanzBalances 0x9e7b40d6 → uint256
saleOneBeanzLimit 0x857b9bd4 → uint256
saleOneCoMuseumBalances 0x2df507be → uint256
saleOneCoMuseumLimit 0x2cb29a0d → uint256
saleTwoAccountBalances 0xcbccdec3 → uint256
saleTwoAccountLimit 0xcd1f5a29 → uint256
signer 0x238ac933 → address
suffix 0xf7073c3a → string
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenPhases 0xc13085db → uint8
tokenURI 0xc87b56dd → string
totalSupply 0x18160ddd → uint256
Write Contract 35 functions
These functions modify contract state and require a wallet transaction to execute.
adminMint 0xa49340cc
address[] accounts_
uint256[] amounts_
adminSetTokensPhase 0xce36774f
tuple request_
bytes signature_
allowTokenTransfer 0xd94917ee
uint256 tokenId
bool allow
approve 0x095ea7b3
address to
uint256 tokenId
decoupleToken 0x0726f720
tuple request_
bytes signature_
initialize 0x5bf6846e
string name_
string symbol_
uint256 maxSupply_
string prefix_
string suffix_
address signer_
lockTokens 0x084b731a
uint256[] tokenIds
pause 0x8456cb59
No parameters
presale 0x030f3c2b
uint256[] coMuseumIds_
uint256[] coMuseumAmounts_
uint256 accountAmount_
tuple request_
bytes signature_
renounceOwnership 0x715018a6
No parameters
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes _data
saleOne 0xd787465c
tuple request_
saleTwo 0xc9672e26
uint256 amount_
setAdminPermissions 0x240ff27f
address account_
bool enable_
setApprovalForAll 0xa22cb465
address operator
bool approved
setMaxSupply 0x6f8b44b0
uint256 maxSupply_
setPhase 0xc03afb59
uint8 phase_
setPrefix 0x85cb593b
string prefix_
setPresaleCoMuseumLimit 0x5eff75c1
uint256 presaleCoMuseumLimit_
setPrice 0x6a00670b
uint8 phase_
uint256 price_
setReservedAmount 0x170e1736
uint256 reservedAmount_
setSaleOneAzukiElementalBeanzLimit 0x73af7a40
uint256 saleOneAzukiElementalBeanzLimit_
setSaleOneAzukiElementalsLimit 0xa9a1d6b0
uint256 saleOneAzukiElementalsLimit_
setSaleOneAzukiLimit 0xf29b4fbc
uint256 saleOneAzukiLimit_
setSaleOneBeanzLimit 0x7c5b35a3
uint256 saleOneBeanzLimit_
setSaleOneCoMuseumLimit 0xde90871f
uint256 saleOneCoMuseumLimit_
setSaleOneStellarLimit 0x8692810c
uint256 saleOneArcStellarsLimit_
setSaleTwoAccountLimit 0x910354c2
uint256 saleTwoAccountLimit_
setSigner 0x6c19e783
address signer_
setSuffix 0x75d5ae9f
string suffix_
transferFrom 0x23b872dd
address from
address to
uint256 tokenId
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
withdraw 0x51cff8d9
address recipient_
Recent Transactions
No transactions found for this address