Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xC4771c27FB631FF6046845d06561bF20eF753DaB
Balance 0 ETH
Nonce 1
Code Size 17670 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

17670 bytes
0x6080604052600436106103b85760003560e01c8063715018a6116101f2578063bec951071161010d578063e7b9e4af116100a0578063ebe356311161006f578063ebe3563114610b8d578063f2fde38b14610bbd578063f3e64a0214610bdd578063f418ad8e14610cbf57600080fd5b8063e7b9e4af14610ae9578063e985e9c514610b09578063eb4883ab14610b44578063eb4ab9e814610b7757600080fd5b8063caa0f92a116100dc578063caa0f92a14610a79578063d082e38114610a8e578063d32aa21c14610aa4578063e6d740e214610ab957600080fd5b8063bec95107146109f1578063c41a360a14610a0d578063c87b56dd14610a43578063c8e74c6914610a6357600080fd5b806395d89b4111610185578063b88d4fde11610154578063b88d4fde14610985578063b9a7d664146109a5578063bc3fb48c146109bb578063bda66ea3146109d157600080fd5b806395d89b41146109045780639a6dee7f146109195780639f67756d14610939578063a22cb4651461096557600080fd5b80638ada6b0f116101c15780638ada6b0f1461089d5780638da5cb5b146108bd578063936bb7cd146108db57806394bf804d146108f157600080fd5b8063715018a61461082857806378f3c5401461083d57806379a617e81461086a57806386ee73311461087d57600080fd5b806337a2dbe1116102e25780634d4018fa1161027557806356d3163d1161024457806356d3163d146107855780636352211e146107a55780636c3a9b4a146107db57806370a08231146107fb57600080fd5b80634d4018fa146107165780634e86ef0c1461072b5780634fe209f91461074b57806354214f691461076b57600080fd5b806345d1e4b1116102b157806345d1e4b11461069657806349df728c146106b65780634b0bddd2146106d65780634b655731146106f657600080fd5b806337a2dbe11461061c5780633bd649681461064c5780633ccfd60b1461066157806342842e0e1461067657600080fd5b80630fdabb5a1161035a578063235329cc11610329578063235329cc1461056a57806323b872dd1461059d57806328cad13d146105bd5780632a55205a146105dd57600080fd5b80630fdabb5a146104ee57806310bf3bed146105045780631e84c4131461051957806320601b141461054b57600080fd5b8063081812fc11610396578063081812fc1461043e578063095ea7b31461048c5780630d3cf1f2146104ae5780630e15b76a146104ce57600080fd5b806301ffc9a7146103bd57806306fdde03146103f257806307e89ec014610414575b600080fd5b3480156103c957600080fd5b506103dd6103d8366004613c12565b610cef565b60405190151581526020015b60405180910390f35b3480156103fe57600080fd5b50610407610d33565b6040516103e99190613c87565b34801561042057600080fd5b50610430670138a388a43c000081565b6040519081526020016103e9565b34801561044a57600080fd5b50610474610459366004613c9a565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016103e9565b34801561049857600080fd5b506104ac6104a7366004613ccf565b610dc1565b005b3480156104ba57600080fd5b506104ac6104c9366004613d07565b610ec4565b3480156104da57600080fd5b506104ac6104e9366004613d69565b610f69565b3480156104fa57600080fd5b50610430600e5481565b34801561051057600080fd5b50610430600481565b34801561052557600080fd5b506006546103dd9074010000000000000000000000000000000000000000900460ff1681565b34801561055757600080fd5b50600d546103dd90610100900460ff1681565b34801561057657600080fd5b5061058a610585366004613dab565b6111da565b60405161ffff90911681526020016103e9565b3480156105a957600080fd5b506104ac6105b8366004613dcd565b611224565b3480156105c957600080fd5b506104ac6105d8366004613d07565b611426565b3480156105e957600080fd5b506105fd6105f8366004613dab565b6114ca565b604080516001600160a01b0390931683526020830191909152016103e9565b34801561062857600080fd5b506103dd610637366004613e09565b600a6020526000908152604090205460ff1681565b34801561065857600080fd5b506104ac61154d565b34801561066d57600080fd5b506104ac6115b6565b34801561068257600080fd5b506104ac610691366004613dcd565b6116c7565b3480156106a257600080fd5b506104ac6106b1366004613c9a565b6117cc565b3480156106c257600080fd5b506104ac6106d1366004613e09565b611849565b3480156106e257600080fd5b506104ac6106f1366004613e24565b6119b4565b34801561070257600080fd5b506104ac610711366004613e7b565b611a39565b34801561072257600080fd5b506104ac611d41565b34801561073757600080fd5b506104ac610746366004613c9a565b611da2565b34801561075757600080fd5b5061058a610766366004613dab565b611e01565b34801561077757600080fd5b50600f546103dd9060ff1681565b34801561079157600080fd5b506104ac6107a0366004613e09565b611e11565b3480156107b157600080fd5b506104746107c0366004613c9a565b6003602052600090815260409020546001600160a01b031681565b3480156107e757600080fd5b506104ac6107f6366004613c9a565b611e9f565b34801561080757600080fd5b50610430610816366004613e09565b60026020526000908152604090205481565b34801561083457600080fd5b506104ac6120e1565b34801561084957600080fd5b5061085d610858366004613c9a565b612147565b6040516103e99190613eb7565b6104ac610878366004613f64565b6122a1565b34801561088957600080fd5b506104ac610898366004613fb7565b6126f2565b3480156108a957600080fd5b50602954610474906001600160a01b031681565b3480156108c957600080fd5b506006546001600160a01b0316610474565b3480156108e757600080fd5b5061043061251c81565b6104ac6108ff366004613fdc565b612778565b34801561091057600080fd5b50610407612b2f565b34801561092557600080fd5b506104ac610934366004614008565b612b3c565b34801561094557600080fd5b50600d546109539060ff1681565b60405160ff90911681526020016103e9565b34801561097157600080fd5b506104ac610980366004613e24565b612bac565b34801561099157600080fd5b506104ac6109a0366004614092565b612c18565b3480156109b157600080fd5b5061043060095481565b3480156109c757600080fd5b5061043060075481565b3480156109dd57600080fd5b506109536109ec36600461413d565b612d04565b3480156109fd57600080fd5b506104306701118f178fb4800081565b348015610a1957600080fd5b50610474610a28366004613c9a565b6000908152600360205260409020546001600160a01b031690565b348015610a4f57600080fd5b50610407610a5e366004613c9a565b612eec565b348015610a6f57600080fd5b50610430600c5481565b348015610a8557600080fd5b506104306130a7565b348015610a9a57600080fd5b50610430602b5481565b348015610ab057600080fd5b506104ac6130bd565b348015610ac557600080fd5b506103dd610ad4366004613c9a565b60116020526000908152604090205460ff1681565b348015610af557600080fd5b506104ac610b04366004613c9a565b613149565b348015610b1557600080fd5b506103dd610b24366004614160565b600560209081526000928352604080842090915290825290205460ff1681565b348015610b5057600080fd5b506006546103dd907501000000000000000000000000000000000000000000900460ff1681565b348015610b8357600080fd5b5061043061019081565b348015610b9957600080fd5b506103dd610ba8366004613e09565b60086020526000908152604090205460ff1681565b348015610bc957600080fd5b506104ac610bd8366004613e09565b6131a8565b348015610be957600080fd5b50610c6b610bf8366004613c9a565b60106020526000908152604090205460ff808216916101008104821691620100008204811691630100000081048216916401000000008204811691650100000000008104821691660100000000000082048116916701000000000000008104821691680100000000000000009091041689565b6040805160ff9a8b168152988a1660208a01529689169688019690965293871660608701529186166080860152851660a0850152841660c0840152831660e0830152909116610100820152610120016103e9565b348015610ccb57600080fd5b506103dd610cda366004613e09565b600b6020526000908152604090205460ff1681565b60006001600160e01b031982167f2a55205a000000000000000000000000000000000000000000000000000000001480610d2d5750610d2d82613287565b92915050565b60008054610d409061418a565b80601f0160208091040260200160405190810160405280929190818152602001828054610d6c9061418a565b8015610db95780601f10610d8e57610100808354040283529160200191610db9565b820191906000526020600020905b815481529060010190602001808311610d9c57829003601f168201915b505050505081565b6000818152600360205260409020546001600160a01b031633811480610e0a57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b610e5b5760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a454400000000000000000000000000000000000060448201526064015b60405180910390fd5b600082815260046020526040808220805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6006546001600160a01b03163314610f1e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b600680549115157501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff909216919091179055565b3360009081526028602052604090205460ff16610fc85760405162461bcd60e51b815260206004820152601060248201527f4d75737420626520616e2061646d696e000000000000000000000000000000006044820152606401610e52565b600c54819061019090610fdc9083906141da565b111561104f5760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f756768206b697474656e732072656d61696e696e6720746f2060448201527f67696674000000000000000000000000000000000000000000000000000000006064820152608401610e52565b61251c81602b5461106091906141da565b11156110ba5760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f756768206b697474656e732072656d61696e696e6720746f206044820152631b5a5b9d60e21b6064820152608401610e52565b600c8054839182916000906110d09084906141da565b909155506000905061113d602a546040516bffffffffffffffffffffffff1933606090811b8216602084015242603484015248605484015241901b166074820152608881019190915260009060a8016040516020818303038152906040528051906020012060001c905090565b905060005b8281101561118c5761117a82878784818110611160576111606141f2565b90506020020160208101906111759190613e09565b613320565b8061118481614208565b915050611142565b50506040516bffffffffffffffffffffffff1933606090811b8216602084015241901b166034820152604801905060408051601f198184030181529190528051602090910120602a55505050565b601282600981106111ea57600080fd5b0181815481106111f957600080fd5b9060005260206000209060109182820401919006600202915091509054906101000a900461ffff1681565b6000818152600360205260409020546001600160a01b0384811691161461128d5760405162461bcd60e51b815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610e52565b6001600160a01b0382166112e35760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610e52565b336001600160a01b038416148061131057506000818152600460205260409020546001600160a01b031633145b8061133e57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b61138a5760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610e52565b6001600160a01b03808416600081815260026020908152604080832080546000190190559386168083528483208054600101905585835260038252848320805473ffffffffffffffffffffffffffffffffffffffff199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6006546001600160a01b031633146114805760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6006805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6000806114d6846134e2565b6115225760405162461bcd60e51b815260206004820152601160248201527f4e6f6e6578697374656e7420746f6b656e0000000000000000000000000000006044820152606401610e52565b600d5430906064906115379060ff1686614222565b6115419190614257565b915091505b9250929050565b6006546001600160a01b031633146115a75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b600f805460ff19166001179055565b6006546001600160a01b031633146116105760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b60006116246006546001600160a01b031690565b6001600160a01b03164760405160006040518083038185875af1925050503d806000811461166e576040519150601f19603f3d011682016040523d82523d6000602084013e611673565b606091505b50509050806116c45760405162461bcd60e51b815260206004820152600f60248201527f5769746864726177206661696c656400000000000000000000000000000000006044820152606401610e52565b50565b6116d2838383611224565b6001600160a01b0382163b158061177b5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af115801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061426b565b6001600160e01b031916145b6117c75760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610e52565b505050565b6006546001600160a01b031633146118265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b600d54610100900460ff166116c457600e55600d805461ff001916610100179055565b6006546001600160a01b031633146118a35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015611903573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119279190614288565b6040517fa9059cbb000000000000000000000000000000000000000000000000000000008152336004820152602481018290529091506001600160a01b0383169063a9059cbb906044016020604051808303816000875af1158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c791906142a1565b6006546001600160a01b03163314611a0e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6001600160a01b03919091166000908152602860205260409020805460ff1916911515919091179055565b3360009081526028602052604090205460ff16611a985760405162461bcd60e51b815260206004820152601060248201527f4d75737420626520616e2061646d696e000000000000000000000000000000006044820152606401610e52565b611aa1836134e2565b611aed5760405162461bcd60e51b815260206004820152600e60248201527f4e6f2073756368206b697474656e0000000000000000000000000000000000006044820152606401610e52565b600060106000611afc8661350c565b8152602081019190915260400160009081209150836008811115611b2257611b226142be565b03611b3957805460ff191660ff8316178155611d3b565b6001836008811115611b4d57611b4d6142be565b03611b6957805461ff00191661010060ff841602178155611d3b565b6002836008811115611b7d57611b7d6142be565b03611bb75780547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff166201000060ff841602178155611d3b565b6003836008811115611bcb57611bcb6142be565b03611beb57805463ff0000001916630100000060ff841602178155611d3b565b6004836008811115611bff57611bff6142be565b03611c3b5780547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffff1664010000000060ff841602178155611d3b565b6005836008811115611c4f57611c4f6142be565b03611c7357805465ff000000000019166501000000000060ff841602178155611d3b565b6006836008811115611c8757611c876142be565b03611cc55780547fffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffff16660100000000000060ff841602178155611d3b565b6007836008811115611cd957611cd96142be565b03611d0157805467ff00000000000000191667010000000000000060ff841602178155611d3b565b6008836008811115611d1557611d156142be565b03611d3b57805468ff000000000000000019166801000000000000000060ff8416021781555b50505050565b6006546001600160a01b03163314611d9b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6000600e55565b6006546001600160a01b03163314611dfc5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b600755565b601b82600981106111ea57600080fd5b3360009081526028602052604090205460ff16611e705760405162461bcd60e51b815260206004820152601060248201527f4d75737420626520616e2061646d696e000000000000000000000000000000006044820152606401610e52565b6029805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b3360009081526028602052604090205460ff16611efe5760405162461bcd60e51b815260206004820152601060248201527f4d75737420626520616e2061646d696e000000000000000000000000000000006044820152606401610e52565b8061019081600c54611f1091906141da565b1115611f835760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f756768206b697474656e732072656d61696e696e6720746f2060448201527f67696674000000000000000000000000000000000000000000000000000000006064820152608401610e52565b61251c81602b54611f9491906141da565b1115611fee5760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f756768206b697474656e732072656d61696e696e6720746f206044820152631b5a5b9d60e21b6064820152608401610e52565b81600c600082825461200091906141da565b909155506000905061206d602a546040516bffffffffffffffffffffffff1933606090811b8216602084015242603484015248605484015241901b166074820152608881019190915260009060a8016040516020818303038152906040528051906020012060001c905090565b905060005b83811015612096576120848233613320565b8061208e81614208565b915050612072565b50506040516bffffffffffffffffffffffff1933606090811b8216602084015241901b16603482015260480160408051601f198184030181529190528051602090910120602a555050565b6006546001600160a01b0316331461213b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6121456000613555565b565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810191909152612199826134e2565b6121e55760405162461bcd60e51b815260206004820152600e60248201527f4e6f2073756368206b697474656e0000000000000000000000000000000000006044820152606401610e52565b601060006121f28461350c565b81526020808201929092526040908101600020815161012081018352905460ff80821683526101008083048216958401959095526201000082048116938301939093526301000000810483166060830152640100000000810483166080830152650100000000008104831660a083015266010000000000008104831660c08301526701000000000000008104831660e08301526801000000000000000090049091169181019190915292915050565b6006547501000000000000000000000000000000000000000000900460ff1661230c5760405162461bcd60e51b815260206004820152601a60248201527f436f6d6d756e6974792073616c65206973206e6f74206f70656e0000000000006044820152606401610e52565b600161251c81602b5461231f91906141da565b11156123795760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f756768206b697474656e732072656d61696e696e6720746f206044820152631b5a5b9d60e21b6064820152608401610e52565b6701118f178fb4800034146123d05760405162461bcd60e51b815260206004820152601860248201527f496e636f7272656374204554482076616c75652073656e7400000000000000006044820152606401610e52565b33600081815260286020526040902054813b919060ff16806123fa575033321480156123fa575081155b6124465760405162461bcd60e51b815260206004820152601760248201527f596f7527726520747279696e6720746f206368656174210000000000000000006044820152606401610e52565b6001600160a01b03861660009081526008602052604090205460ff16156125c0576001600160a01b0386166000908152600a602052604090205460ff16156124d05760405162461bcd60e51b815260206004820152600f60248201527f416c726561647920636c61696d656400000000000000000000000000000000006044820152606401610e52565b6124de8585600954896135b4565b61252a5760405162461bcd60e51b815260206004820152600f60248201527f416c726561647920636c61696d656400000000000000000000000000000000006044820152606401610e52565b6001600160a01b0386166000908152600a60205260409020805460ff191660011790556125bb6125b5602a546040516bffffffffffffffffffffffff1933606090811b8216602084015242603484015248605484015241901b166074820152608881019190915260009060a8016040516020818303038152906040528051906020012060001c905090565b87613320565b6126a5565b6125ce8585600754896135b4565b61261a5760405162461bcd60e51b815260206004820152601360248201527f41646472657373206e6f7420696e206c697374000000000000000000000000006044820152606401610e52565b6001600160a01b0386166000908152600860205260409020805460ff191660011790556126a56125b5602a546040516bffffffffffffffffffffffff1933606090811b8216602084015242603484015248605484015241901b166074820152608881019190915260009060a8016040516020818303038152906040528051906020012060001c905090565b6040516bffffffffffffffffffffffff19606083811b8216602084015241901b1660348201526048015b60408051601f198184030181529190528051602090910120602a55505050505050565b6000828152600360205260409020546001600160a01b031633146127585760405162461bcd60e51b815260206004820152600f60248201527f4e6f7420796f7572206b697474656e00000000000000000000000000000000006044820152606401610e52565b600091825260116020526040909120805460ff1916911515919091179055565b60065474010000000000000000000000000000000000000000900460ff166127e25760405162461bcd60e51b815260206004820152601760248201527f5075626c69632073616c65206973206e6f74206f70656e0000000000000000006044820152606401610e52565b81600081116128335760405162461bcd60e51b815260206004820152601060248201527f43616e6e6f74206d696e74207a65726f000000000000000000000000000000006044820152606401610e52565b60048111156128845760405162461bcd60e51b815260206004820152601c60248201527f4d6178206b697474656e7320746f206d696e74206578636565646564000000006044820152606401610e52565b61251c81602b5461289591906141da565b11156128ef5760405162461bcd60e51b8152602060048201526024808201527f4e6f7420656e6f756768206b697474656e732072656d61696e696e6720746f206044820152631b5a5b9d60e21b6064820152608401610e52565b8260246128fd6001836142d4565b6004811061290d5761290d6141f2565b015461292182670138a388a43c0000614222565b61292b91906141da565b34146129795760405162461bcd60e51b815260206004820152601860248201527f496e636f7272656374204554482076616c75652073656e7400000000000000006044820152606401610e52565b33600081815260286020526040902054813b919060ff16806129a3575033321480156129a3575081155b6129ef5760405162461bcd60e51b815260206004820152601760248201527f596f7527726520747279696e6720746f206368656174210000000000000000006044820152606401610e52565b336000908152600b602052604090205460ff1615612a4f5760405162461bcd60e51b815260206004820152600e60248201527f416c7265616479206d696e7465640000000000000000000000000000000000006044820152606401610e52565b336000908152600b60205260408120805460ff19166001179055612ace602a546040516bffffffffffffffffffffffff1933606090811b8216602084015242603484015248605484015241901b166074820152608881019190915260009060a8016040516020818303038152906040528051906020012060001c905090565b905060005b878167ffffffffffffffff161015612aff57612aef8288613320565b612af8816142eb565b9050612ad3565b50506040516bffffffffffffffffffffffff19606083811b8216602084015241901b1660348201526048016126cf565b60018054610d409061418a565b6006546001600160a01b03163314612b965760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b600d805460ff191660ff92909216919091179055565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b612c23848484611224565b6001600160a01b0383163b1580612cb85750604051630a85bd0160e11b808252906001600160a01b0385169063150b7a0290612c69903390899088908890600401614312565b6020604051808303816000875af1158015612c88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cac919061426b565b6001600160e01b031916145b611d3b5760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610e52565b6000612d0f836134e2565b612d5b5760405162461bcd60e51b815260206004820152600e60248201527f4e6f2073756368206b697474656e0000000000000000000000000000000000006044820152606401610e52565b600060106000612d6a8661350c565b8152602081019190915260400160009081209150836008811115612d9057612d906142be565b03612da0575460ff169050610d2d565b6001836008811115612db457612db46142be565b03612dc95754610100900460ff169050610d2d565b6002836008811115612ddd57612ddd6142be565b03612df3575462010000900460ff169050610d2d565b6003836008811115612e0757612e076142be565b03612e1e57546301000000900460ff169050610d2d565b6004836008811115612e3257612e326142be565b03612e4a5754640100000000900460ff169050610d2d565b6005836008811115612e5e57612e5e6142be565b03612e77575465010000000000900460ff169050610d2d565b6006836008811115612e8b57612e8b6142be565b03612ea557546601000000000000900460ff169050610d2d565b6007836008811115612eb957612eb96142be565b03612ed45754670100000000000000900460ff169050610d2d565b5468010000000000000000900460ff16905092915050565b6060612ef7826134e2565b612f435760405162461bcd60e51b815260206004820152601160248201527f4e6f6e6578697374656e7420746f6b656e0000000000000000000000000000006044820152606401610e52565b600f5460ff16612fd7576029546040517f3278a957000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690633278a95790602401600060405180830381865afa158015612faf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2d919081019061434e565b600060106000612fe68561350c565b8152602080820192909252604090810160009081206029548783526011909452908290205491517fca9da47a0000000000000000000000000000000000000000000000000000000081529093506001600160a01b039092169163ca9da47a9161305b918791869160ff909116906004016143c5565b600060405180830381865afa158015613078573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130a0919081019061434e565b9392505050565b6000602b5460016130b891906141da565b905090565b6006546001600160a01b031633146131175760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6040805160808101825260008082526020820181905291810182905260608101919091526116c4906024906004613ba4565b6006546001600160a01b031633146131a35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b600955565b6006546001600160a01b031633146132025760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e52565b6001600160a01b03811661327e5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610e52565b6116c481613555565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b0319831614806132ea57507f80ac58cd000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b80610d2d5750506001600160e01b0319167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b600061332a613634565b6040805160208082018790528183018490528251808303840181526060909201909252805191012090915061335e90613650565b6000828152601060209081526040918290208351815492850151938501516060860151608087015160a088015160c089015160e08a01516101009a8b015160ff9788167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909a1699909917998716909a02989098177fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff16620100009486169490940263ff000000191693909317630100000092851692909202919091177fffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffff166401000000009184169190910265ff00000000001916176501000000000091831691909102177fffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff1666010000000000009482169490940267ff00000000000000191693909317670100000000000000948416949094029390931768ff000000000000000019166801000000000000000092909116919091021790556117c78282613806565b6000818152600360205260408120546001600160a01b031615801590610d2d57505061251c101590565b600d54600090610100900460ff1615806135265750600e54155b1561352f575090565b61251c600e548361354091906141da565b61354a9190614475565b610d2d9060016141da565b600680546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000613629858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250506040516bffffffffffffffffffffffff19606088901b166020820152879250603401905060405160208183030381529060405280519060200120613906565b90505b949350505050565b6000602b6000815461364590614208565b9091555050602b5490565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091526136a88261ffff16600061391c565b6136b3906001614489565b60ff16815260109190911c906136ce61ffff8316600161391c565b6136d9906001614489565b60ff16602082015260109190911c906136f761ffff8316600261391c565b613702906001614489565b60ff16604082015260109190911c9061372061ffff8316600361391c565b61372b906001614489565b60ff16606082015260109190911c9061374961ffff8316600461391c565b613754906001614489565b60ff16608082015260109190911c9061377261ffff8316600561391c565b61377d906001614489565b60ff1660a082015260109190911c9061379b61ffff8316600661391c565b6137a6906001614489565b60ff1660c082015260109190911c906137c461ffff8316600761391c565b6137cf906001614489565b60ff1661010082015260109190911c906137ee61ffff8316600861391c565b6137f9906001614489565b60ff1660e0820152919050565b61381082826139fd565b6001600160a01b0382163b15806138b65750604051630a85bd0160e11b80825233600483015260006024830181905260448301849052608060648401526084830152906001600160a01b0384169063150b7a029060a4016020604051808303816000875af1158015613886573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138aa919061426b565b6001600160e01b031916145b6139025760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610e52565b5050565b6000826139138584613b30565b14949350505050565b60008060128360ff1660098110613935576139356141f2565b015461394190856144ae565b905060128360ff1660098110613959576139596141f2565b018160ff168154811061396e5761396e6141f2565b60009182526020909120601082040154600f9091166002026101000a900461ffff16600885901c60ff1610156139a5579050610d2d565b601b8360ff16600981106139bb576139bb6141f2565b018160ff16815481106139d0576139d06141f2565b90600052602060002090601091828204019190066002029054906101000a900461ffff1691505092915050565b6001600160a01b038216613a535760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610e52565b6000818152600360205260409020546001600160a01b031615613ab85760405162461bcd60e51b815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610e52565b6001600160a01b0382166000818152600260209081526040808320805460010190558483526003909152808220805473ffffffffffffffffffffffffffffffffffffffff19168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600081815b8451811015613b9c576000858281518110613b5257613b526141f2565b60200260200101519050808311613b785760008381526020829052604090209250613b89565b600081815260208490526040902092505b5080613b9481614208565b915050613b35565b509392505050565b8260048101928215613bd7579160200282015b82811115613bd7578251829060ff16905591602001919060010190613bb7565b50613be3929150613be7565b5090565b5b80821115613be35760008155600101613be8565b6001600160e01b0319811681146116c457600080fd5b600060208284031215613c2457600080fd5b81356130a081613bfc565b60005b83811015613c4a578181015183820152602001613c32565b83811115611d3b5750506000910152565b60008151808452613c73816020860160208601613c2f565b601f01601f19169290920160200192915050565b6020815260006130a06020830184613c5b565b600060208284031215613cac57600080fd5b5035919050565b80356001600160a01b0381168114613cca57600080fd5b919050565b60008060408385031215613ce257600080fd5b613ceb83613cb3565b946020939093013593505050565b80151581146116c457600080fd5b600060208284031215613d1957600080fd5b81356130a081613cf9565b60008083601f840112613d3657600080fd5b50813567ffffffffffffffff811115613d4e57600080fd5b6020830191508360208260051b850101111561154657600080fd5b60008060208385031215613d7c57600080fd5b823567ffffffffffffffff811115613d9357600080fd5b613d9f85828601613d24565b90969095509350505050565b60008060408385031215613dbe57600080fd5b50508035926020909101359150565b600080600060608486031215613de257600080fd5b613deb84613cb3565b9250613df960208501613cb3565b9150604084013590509250925092565b600060208284031215613e1b57600080fd5b6130a082613cb3565b60008060408385031215613e3757600080fd5b613e4083613cb3565b91506020830135613e5081613cf9565b809150509250929050565b803560098110613cca57600080fd5b803560ff81168114613cca57600080fd5b600080600060608486031215613e9057600080fd5b83359250613ea060208501613e5b565b9150613eae60408501613e6a565b90509250925092565b60006101208201905060ff835116825260ff60208401511660208301526040830151613ee8604084018260ff169052565b506060830151613efd606084018260ff169052565b506080830151613f12608084018260ff169052565b5060a0830151613f2760a084018260ff169052565b5060c0830151613f3c60c084018260ff169052565b5060e0830151613f5160e084018260ff169052565b506101009283015160ff16919092015290565b600080600060408486031215613f7957600080fd5b613f8284613cb3565b9250602084013567ffffffffffffffff811115613f9e57600080fd5b613faa86828701613d24565b9497909650939450505050565b60008060408385031215613fca57600080fd5b823591506020830135613e5081613cf9565b60008060408385031215613fef57600080fd5b82359150613fff60208401613cb3565b90509250929050565b60006020828403121561401a57600080fd5b6130a082613e6a565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561406257614062614023565b604052919050565b600067ffffffffffffffff82111561408457614084614023565b50601f01601f191660200190565b600080600080608085870312156140a857600080fd5b6140b185613cb3565b93506140bf60208601613cb3565b925060408501359150606085013567ffffffffffffffff8111156140e257600080fd5b8501601f810187136140f357600080fd5b80356141066141018261406a565b614039565b81815288602083850101111561411b57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561415057600080fd5b82359150613fff60208401613e5b565b6000806040838503121561417357600080fd5b61417c83613cb3565b9150613fff60208401613cb3565b600181811c9082168061419e57607f821691505b6020821081036141be57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082198211156141ed576141ed6141c4565b500190565b634e487b7160e01b600052603260045260246000fd5b6000600019820361421b5761421b6141c4565b5060010190565b600081600019048311821515161561423c5761423c6141c4565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261426657614266614241565b500490565b60006020828403121561427d57600080fd5b81516130a081613bfc565b60006020828403121561429a57600080fd5b5051919050565b6000602082840312156142b357600080fd5b81516130a081613cf9565b634e487b7160e01b600052602160045260246000fd5b6000828210156142e6576142e66141c4565b500390565b600067ffffffffffffffff808316818103614308576143086141c4565b6001019392505050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526143446080830184613c5b565b9695505050505050565b60006020828403121561436057600080fd5b815167ffffffffffffffff81111561437757600080fd5b8201601f8101841361438857600080fd5b80516143966141018261406a565b8181528560208385010111156143ab57600080fd5b6143bc826020830160208601613c2f565b95945050505050565b838152825460ff8082166020840152600882901c81166040840152601082901c81166060840152601882901c811660808401526101608301919061441360a08501828460201c1660ff169052565b61442760c08501828460281c1660ff169052565b61443b60e08501828460301c1660ff169052565b6144506101008501828460381c1660ff169052565b6144656101208501828460401c1660ff169052565b505082151561014083015261362c565b60008261448457614484614241565b500690565b600060ff821660ff84168060ff038211156144a6576144a66141c4565b019392505050565b600060ff8316806144c1576144c1614241565b8060ff8416069150509291505056fea264697066735822122099456596653435b1e299f2e0acad374df6b5be1204d9232652b73507bda4e57a64736f6c634300080d0033

Verified Source Code Full Match

Compiler: v0.8.13+commit.abaa5c0e EVM: london Optimization: Yes (2000 runs)
Kitten.sol 683 lines
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC2981.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

import "@rari-capital/solmate/src/tokens/ERC721.sol";

import "./interfaces/IKitten.sol";
import "./interfaces/IMetadata.sol";

/// @title Kitten
/// @author kitten devs
/// @notice h/t crypto coven for some beautiful ERC721 inspiration.
contract Kitten is IKitten, ERC721, IERC2981, Ownable {
    /// STORAGE ///

    /// @notice Allowed max supply of Kittens.
    uint256 public constant MAX_KITTENS = 9500;

    /// @notice Per-wallet Kitten cap.
    uint256 public constant MAX_KITTENS_PER_WALLET = 4;

    /// @notice Public sale.
    bool public isPublicSaleActive;
    uint256 public constant PUBLIC_SALE_PRICE = 0.088 ether;

    /// @notice Community sale (determined in Discord).
    bool public isCommunitySaleActive;
    uint256 public constant COMMUNITY_SALE_PRICE = 0.077 ether;

    /// @notice Merkle root for first community sale claims.
    bytes32 public communityFirstClaimMerkleRoot;

    /// @notice Addresses that have claimed a first community mint.
    mapping(address => bool) public claimedFirst;

    /// @notice Second community sale list for addresses with two claims.
    bytes32 public communitySecondClaimMerkleRoot;

    /// @notice Addresses that have claimed a second community mint.
    mapping(address => bool) public claimedSecond;

    /// @notice Counters for addresses that have participated in public sale.
    mapping(address => bool) public publicSaleParticipants;

    /// @notice Team + gift kittens.
    uint256 public numGiftedKittens;
    uint256 public constant MAX_GIFTED_KITTENS = 400;

    /// @notice Royalty percentage. Must be an integer percentage.
    uint8 public royaltyPercent = 5;

    /// @notice Shifting kitten metadata prereveal.
    bool public hasShifted = false;
    uint256 public metadataOffset = 0;

    /// @notice Metadata reveal trigger.
    bool public isRevealed = false;

    /// @notice Mapping of token ID to traits.
    mapping(uint256 => Kitten) public kittens;

    /// @notice Mapping of Kittens using special renderer.
    mapping(uint256 => bool) public specialMode;

    /// @notice List of probabilities for each trait type.
    uint16[][9] public traitRarities;

    /// @notice List of aliases for AJ Walker's Alias Algorithm.
    uint16[][9] public traitAliases;

    /// @notice Sauce up the prices.
    uint256[4] private sauce = [
        0.00002 ether,
        0.00006 ether,
        0.00001 ether,
        0.00007 ether
    ];

    /// @notice Addresses that can perform admin functionality, e.g. gifting.
    mapping(address => bool) private admins;

    /// @notice Address of the metadata renderer.
    address public renderer;

    /// @notice Used for increased pseudorandomness.
    bytes32 private entropy;

    /// @notice Counter of minted tokens.
    uint256 public tokenCounter;

    /// CONSTRUCTOR ///

    constructor() ERC721("WarKitten", "KITTEN") {
        // This looks insane, but it works.

        // Backgrounds.
        traitRarities[0] = [
            232, 201,  77,  70, 47, 136,
            174,  93, 110, 232, 77, 115,
            118, 117, 198, 121, 56,  61,
            62, 106, 106, 255, 52
        ];
        traitAliases[0] = [
            1,  5,
            0,  1,
            1,  6,
            8,  5,
            9,  10,
            11, 12,
            14, 8,
            15, 21,
            8,  9,
            10, 12,
            12, 0,
            15
        ];

        // Bodies.
        traitRarities[1] = [
            167, 192, 215,  98, 221, 252, 165, 207, 210, 133,
            184, 182, 109, 219, 143, 202,  61, 249, 207, 196,
            185, 214, 143, 120, 135,  76, 109, 233, 168, 247,
            141, 176,  56, 143, 109, 130, 204, 148, 170, 240,
            232, 165, 165, 143, 250, 244, 201, 245,  72, 131,
            139, 200, 120, 207, 133, 173,  63,  70,  83, 185,
            223, 253, 120, 126, 165, 193, 120, 255, 128
        ];
        traitAliases[1] = [
            1,  2,  4,  1,
            8,  2,  2,  2,
            9,  10, 15, 2,
            4,  4,  4,  17,
            8,  21, 9,  9,
            9,  27, 9,  9,
            15, 17, 21, 28,
            29, 30, 38, 21,
            28, 29, 29, 30,
            38, 38, 39, 45,
            38, 38, 39, 45,
            45, 46, 47, 48,
            51, 45, 46, 54,
            47, 47, 55, 60,
            48, 54, 61, 61,
            61, 63, 63, 65,
            65, 67, 65, 0,
            67
        ];

        // Clothes.
        traitRarities[2] = [
            201, 251, 190, 122, 143,  97,  46, 224, 233, 131, 203,
            253, 194, 153, 153, 153,  56, 126,  81,  66, 106,  97,
            62,  50,  50,  72,  50,  50,  81, 179, 153,  72, 253,
            184, 228, 112, 130, 108,  62,  62, 131, 153, 108, 151,
            234,  91, 203, 111, 233, 102,  54,  72,  85,  58, 184,
            153, 112,  81, 131,  91,  31, 215, 117, 203, 153, 212,
            97, 153, 184, 218, 114, 255
        ];
        traitAliases[2] = [
            1,  2,  8,  0,  2,  8, 12, 12, 12, 12, 29, 29,
            29, 29, 34, 34, 36, 43, 47, 61, 62, 65, 69, 69,
            70, 70, 70, 71, 71, 34, 71, 71, 71, 71, 36, 71,
            43, 71, 71, 71, 71, 71, 71, 44, 47, 71, 71, 48,
            61, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
            71, 62, 65, 71, 71, 69, 71, 71, 71, 70, 71, 0
        ];

        // Ears.
        traitRarities[3] = [
            23,  26,  52,  35, 152,
            158, 200, 107, 157,  30,
            87, 189, 255
        ];
        traitAliases[3] = [
            4,  7, 7, 11,  5,
            6,  7, 8, 11, 11,
            12, 12, 0
        ];

        // Eyes.
        traitRarities[4] = [
            51,  70, 187, 151, 126, 163,  60,
            51,  27,  30,  97, 237,  69, 249,
            19,  34, 163,  90, 144, 117, 105,
            125, 169, 136,  27,  90, 109,  47,
            255
        ];
        traitAliases[4] = [
            4, 28, 28, 28,  5, 22, 28, 28,
            28, 28, 28, 28, 28, 28, 28, 28,
            28, 28, 28, 28, 28, 28, 28, 28,
            28, 28, 28, 28, 0
        ];

        // Heads.
        traitRarities[5] = [
            145, 127,  47,  13,  27, 221, 228, 147, 241, 114,  65, 199,
            49,  29, 215,  51,  98, 255, 189,  53,  56,  58,  32,  42,
            67, 209,  89, 212,  60,  45,  31,  33,  16,  20,  40,  62,
            168, 189, 131,  36, 105, 216,  74,  87, 155, 252,  71,  71,
            118, 193, 216,  67, 196, 203,  78, 242,  22, 145,  46,  89,
            100, 123, 221, 147, 167,  25,  38, 125, 138, 214, 143, 190,
            232,  74, 175,  40, 216, 221, 218, 130, 242, 191, 255
        ];
        traitAliases[5] = [
            6, 11, 16, 22, 37, 37,  8, 37, 11, 41, 43, 14,
            48, 58, 16, 62, 17, 22, 71, 73, 79, 81, 26, 82,
            82, 82, 36, 82, 82, 82, 82, 82, 82, 82, 82, 82,
            37, 41, 82, 82, 82, 43, 82, 44, 45, 48, 82, 82,
            49, 50, 55, 82, 82, 82, 82, 58, 82, 82, 61, 82,
            82, 62, 71, 82, 82, 82, 82, 82, 82, 82, 82, 72,
            73, 74, 77, 82, 82, 79, 82, 80, 81, 82, 0
        ];

        // Necks.
        traitRarities[6] = [
            67,  70, 23, 86,  51,
            56, 121, 67, 60, 255
        ];
        traitAliases[6] = [
            9, 9, 9, 9, 9,
            9, 9, 9, 9, 0
        ];

        // Paws.
        traitRarities[7] = [
            193, 133, 111, 230, 106,  89,  59, 126,  94, 197,  94,
            236, 239, 115, 198,  85,  24, 204,  28, 150,  78,  80,
            217, 222,  90, 128, 120,  48, 130, 188, 122, 192,  61,
            63,  67,  69,  70,  87,  33,  97, 120, 232, 124,  89,
            99, 218,  41, 244,  93, 230, 107, 239,  96,  81, 109,
            85,  74,  25,  98,  87, 254, 130, 102, 165,  56,  78,
            250, 119, 255
        ];
        traitAliases[7] = [
            1,  3,  0,  8,  1,  8, 24, 28,  9, 11, 39, 12,
            24, 44, 44, 44, 57, 65, 65, 67, 67, 68, 68, 68,
            28, 68, 68, 68, 29, 31, 68, 39, 68, 68, 68, 68,
            68, 68, 68, 40, 41, 44, 68, 68, 45, 47, 68, 57,
            68, 68, 68, 68, 68, 68, 68, 68, 68, 63, 68, 68,
            68, 68, 68, 65, 68, 66, 67, 68, 0
        ];

        // Special.
        traitRarities[8] = [
            12, 10,   8, 14,
            19, 17, 255
        ];
        traitAliases[8] = [
            6, 6, 6, 6, 6, 6, 0
        ];
    }

    /// MODIFIERS ///

    /// @notice Some anti-bot restrictions.
    modifier noCheats() {
        uint256 size = 0;
        address account = msg.sender;
        assembly {
            size := extcodesize(account)
        }

        require(
            admins[msg.sender] || (msg.sender == tx.origin && size == 0),
            "You're trying to cheat!"
        );
        _;

        // Use the last caller hash to add entropy to next caller.
        entropy = keccak256(abi.encodePacked(account, block.coinbase));
    }

    modifier increaseEntropy() {
        _;

        // Use the last caller hash to add entropy to next caller.
        entropy = keccak256(abi.encodePacked(msg.sender, block.coinbase));
    }

    modifier onlyAdmin() {
        require(admins[msg.sender], "Must be an admin");
        _;
    }

    modifier publicSaleActive() {
        require(isPublicSaleActive, "Public sale is not open");
        _;
    }

    modifier communitySaleActive() {
        require(isCommunitySaleActive, "Community sale is not open");
        _;
    }

    modifier canMintKittens(uint256 numberOfTokens) {
        require(numberOfTokens > 0, "Cannot mint zero");
        require(numberOfTokens <= MAX_KITTENS_PER_WALLET, "Max kittens to mint exceeded");
        require(
            tokenCounter + numberOfTokens <= MAX_KITTENS,
            "Not enough kittens remaining to mint"
        );
        _;
    }

    modifier canGiftKittens(uint256 num) {
        require(
            numGiftedKittens + num <= MAX_GIFTED_KITTENS,
            "Not enough kittens remaining to gift"
        );
        require(
            tokenCounter + num <= MAX_KITTENS,
            "Not enough kittens remaining to mint"
        );
        _;
    }

    modifier isCorrectCommunitySalePayment() {
        require(msg.value == COMMUNITY_SALE_PRICE, "Incorrect ETH value sent");
        _;
    }

    modifier isCorrectPublicSalePayment(uint256 number) {
        require(msg.value == (PUBLIC_SALE_PRICE * number) + sauce[number - 1], "Incorrect ETH value sent");
        _;
    }

    /// MINTING ///

    function mint(uint256 amount, address to)
        external
        payable
        publicSaleActive
        canMintKittens(amount)
        isCorrectPublicSalePayment(amount)
        noCheats
    {
        require(!publicSaleParticipants[msg.sender], "Already minted");

        publicSaleParticipants[msg.sender] = true;

        uint256 seed = _rand();
        for (uint64 i = 0; i < amount; ++i) {
            _mintKitten(seed, to);
        }
    }

    function mintCommunitySale(
        address to,
        bytes32[] calldata merkleProof
    )
        external
        payable
        communitySaleActive
        canMintKittens(1)
        isCorrectCommunitySalePayment
        noCheats
    {
        // We have two checks here, since some addresses have two claims.

        if (claimedFirst[to]) {
            // Check for second claim.
            require(!claimedSecond[to], "Already claimed");

            require(_isValidMerkleProof(merkleProof, communitySecondClaimMerkleRoot, to), "Already claimed");

            claimedSecond[to] = true;
            _mintKitten(_rand(), to);
        } else {
            // First claim.
            require(_isValidMerkleProof(merkleProof, communityFirstClaimMerkleRoot, to), "Address not in list");

            claimedFirst[to] = true;
            _mintKitten(_rand(), to);
        }
    }

    function reserveForGifting(uint256 amount)
        external
        onlyAdmin
        canGiftKittens(amount)
        increaseEntropy
    {
        numGiftedKittens += amount;

        uint256 seed = _rand();
        for (uint256 i = 0; i < amount; i++) {
            _mintKitten(seed, msg.sender);
        }
    }

    function giftKittens(address[] calldata addresses)
        external
        onlyAdmin
        canGiftKittens(addresses.length)
        increaseEntropy
    {
        uint256 numToGift = addresses.length;
        numGiftedKittens += numToGift;

        uint256 seed = _rand();
        for (uint256 i = 0; i < numToGift; i++) {
            _mintKitten(seed, addresses[i]);
        }
    }

    function _mintKitten(uint256 seed, address to) internal {
        uint256 tokenId = _getNextTokenId();
        kittens[tokenId] = selectTraits(_randomize(seed, tokenId));

        _safeMint(to, tokenId);
    }

    /// IKITTEN ///

    function getOwner(uint256 tokenId) public view returns (address) {
        return ownerOf[tokenId];
    }

    function getNextTokenId() public view returns (uint256) {
        return tokenCounter + 1;
    }

    function getKitten(uint256 tokenId) public view returns (Kitten memory) {
        require(_exists(tokenId), "No such kitten");

        return kittens[_getOffsetTokenId(tokenId)];
    }

    /// @notice Returns a single trait value for a Kitten.
    function getTrait(uint256 tokenId, Trait trait) public view returns (uint8) {
        require(_exists(tokenId), "No such kitten");

        Kitten storage kitten = kittens[_getOffsetTokenId(tokenId)];

        if (trait == Trait.Background)      return kitten.background;
        else if (trait == Trait.Body)       return kitten.body;
        else if (trait == Trait.Clothes)    return kitten.clothes;
        else if (trait == Trait.Ears)       return kitten.ears;
        else if (trait == Trait.Eyes)       return kitten.eyes;
        else if (trait == Trait.Head)       return kitten.head;
        else if (trait == Trait.Neck)       return kitten.neck;
        else if (trait == Trait.Special)    return kitten.special;
        else return kitten.weapon;
    }

    /// @notice Updates a single trait for a Kitten.
    /// @dev Used for swapping traits after battles.
    function updateTrait(uint256 tokenId, Trait trait, uint8 value) public onlyAdmin {
        require(_exists(tokenId), "No such kitten");

        Kitten storage kitten = kittens[_getOffsetTokenId(tokenId)];

        if (trait == Trait.Background)      kitten.background = value;
        else if (trait == Trait.Body)       kitten.body = value;
        else if (trait == Trait.Clothes)    kitten.clothes = value;
        else if (trait == Trait.Ears)       kitten.ears = value;
        else if (trait == Trait.Eyes)       kitten.eyes = value;
        else if (trait == Trait.Head)       kitten.head = value;
        else if (trait == Trait.Neck)       kitten.neck = value;
        else if (trait == Trait.Special)    kitten.special = value;
        else if (trait == Trait.Weapon)     kitten.weapon = value;
    }

    /// @notice Toggle the Kitten's mode.
    function setKittenMode(uint256 tokenId, bool special) external {
        // Must be sender's Kitten.
        require(ownerOf[tokenId] == msg.sender, "Not your kitten");

        specialMode[tokenId] = special;
    }

    /// HELPERS ///

    function _isValidMerkleProof(
        bytes32[] calldata merkleProof,
        bytes32 root,
        address account
    ) internal pure returns (bool) {
        return MerkleProof.verify(
            merkleProof,
            root,
            keccak256(abi.encodePacked(account))
        );
    }

    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return ownerOf[tokenId] != address(0) && tokenId <= MAX_KITTENS;
    }

    /// @notice Returns a shifted token ID once we've performed the reveal shift.
    /// @dev Ensure the shift is done *before* reveal is toggled.
    function _getOffsetTokenId(uint256 tokenId) internal view virtual returns (uint256) {
        if (!hasShifted || metadataOffset == 0) {
            return tokenId;
        }

        return ((tokenId + metadataOffset) % MAX_KITTENS) + 1;
    }

    function _getNextTokenId() private returns (uint256) {
        ++ tokenCounter;
        return tokenCounter;
    }

    /// TRAITS ///

    /// @notice Uses AJ Walker's Alias algorithm for O(1) rarity table lookup.
    /// @notice Ensures O(1) instead of O(n), reduces mint cost.
    /// @notice Probability & alias tables are generated off-chain beforehand.
    function selectTrait(uint16 seed, uint8 traitType)
        internal
        view
        returns (uint8)
    {
        uint8 trait = uint8(seed) % uint8(traitRarities[traitType].length);
        // If a selected random trait probability is selected (biased coin) return that trait.
        if (seed >> 8 < traitRarities[traitType][trait]) return trait;
        return uint8(traitAliases[traitType][trait]);
    }

    /// @notice Constructs a Kitten with weighted random attributes.
    function selectTraits(uint256 seed)
        internal
        view
        returns (Kitten memory kitten)
    {

        kitten.background   = selectTrait(uint16(seed & 0xFFFF), 0) + 1;
        seed >>= 16;
        kitten.body         = selectTrait(uint16(seed & 0xFFFF), 1) + 1;
        seed >>= 16;
        kitten.clothes      = selectTrait(uint16(seed & 0xFFFF), 2) + 1;
        seed >>= 16;
        kitten.ears         = selectTrait(uint16(seed & 0xFFFF), 3) + 1;
        seed >>= 16;
        kitten.eyes         = selectTrait(uint16(seed & 0xFFFF), 4) + 1;
        seed >>= 16;
        kitten.head         = selectTrait(uint16(seed & 0xFFFF), 5) + 1;
        seed >>= 16;
        kitten.neck         = selectTrait(uint16(seed & 0xFFFF), 6) + 1;
        seed >>= 16;
        kitten.weapon       = selectTrait(uint16(seed & 0xFFFF), 7) + 1;
        seed >>= 16;
        kitten.special      = selectTrait(uint16(seed & 0xFFFF), 8) + 1;
    }

    /// ADMIN ///

    /// @notice Adds or removes an admin address.
    function setAdmin(address admin, bool isAdmin) external onlyOwner {
        admins[admin] = isAdmin;
    }

    function setRenderer(address _renderer) external onlyAdmin {
        renderer = _renderer;
    }

    function setIsPublicSaleActive(bool _isPublicSaleActive)
        external
        onlyOwner
    {
        isPublicSaleActive = _isPublicSaleActive;
    }

    function setIsCommunitySaleActive(bool _isCommunitySaleActive)
        external
        onlyOwner
    {
        isCommunitySaleActive = _isCommunitySaleActive;
    }

    function setFirstCommunityListMerkleRoot(bytes32 merkleRoot) external onlyOwner {
        communityFirstClaimMerkleRoot = merkleRoot;
    }

    function setSecondCommunityListMerkleRoot(bytes32 merkleRoot) external onlyOwner {
        communitySecondClaimMerkleRoot = merkleRoot;
    }

    function setRoyaltyPercentage(uint8 percent) external onlyOwner {
        royaltyPercent = percent;
    }

    /// @notice Sets a shifted metadata offset so that Kitten traits aren't mapped precisely to token ID.
    /// @notice This ensures you can't predict which Kitten traits you'll get at mint time.
    /// @dev The actual offset ends up being this offset + 1, since we do a modulo on the supply and start with token 1.
    function setMetadataOffset(uint256 offset) external onlyOwner {
        if (!hasShifted) {
            metadataOffset = offset;
            hasShifted = true;
        }
    }

    /// @notice Resets the metadata shift offset to 0 in case something unexpected happens.
    /// @dev We wouldn't be able to shift again, since the offset is a one-time setter (no rugs!).
    function resetMetadataOffset() external onlyOwner {
        metadataOffset = 0;
    }

    function setRevealed() external onlyOwner {
        isRevealed = true;
    }

    /// @notice Break glass in case of emergency.
    function deSauce() external onlyOwner {
        sauce = [0, 0, 0, 0];
    }

    /// @notice Send contract balance to owner.
    function withdraw() external onlyOwner {
        (bool success, ) = owner().call{value: address(this).balance}("");
        require(success, "Withdraw failed");
    }

    /// @notice Do our best to get mistakenly sent ERC20s out of the contract.
    function withdrawTokens(address token) external onlyOwner {
        uint256 balance = IERC20(token).balanceOf(address(this));
        IERC20(token).transfer(msg.sender, balance);
    }

    /// RANDOMNESS ///

    /// @notice Create a bit more randomness by hashing a seed with another input value.
    /// @dev We do this to "re-hash" pseudorandom values within the same tx.
    /// @dev h/t 0xBasset.
    function _randomize(uint256 rand, uint256 zest) internal pure returns (uint256) {
        return uint256(keccak256(abi.encode(rand, zest)));
    }

    /// @notice Generates a pseudorandom number based on the current block and caller.
    /// @dev This will be the same if called in the same tx without changing entropy.
    function _rand() internal view returns (uint256) {
        return uint256(keccak256(abi.encodePacked(msg.sender, block.timestamp, block.basefee, block.coinbase, entropy)));
    }

    /// OVERRIDES ///

    function supportsInterface(bytes4 interfaceId)
        public
        pure
        virtual
        override(ERC721, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(IERC2981).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(_exists(tokenId), "Nonexistent token");

        if (!isRevealed) {
            return IMetadata(renderer).getPlaceholderURI(tokenId);
        }

        Kitten storage kitten = kittens[_getOffsetTokenId(tokenId)];
        return IMetadata(renderer).getTokenURI(tokenId, kitten, specialMode[tokenId]);
    }

    /// @notice Royalty metadata.
    /// @dev See {IERC165-royaltyInfo}.
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        override
        returns (address receiver, uint256 royaltyAmount)
    {
        require(_exists(tokenId), "Nonexistent token");

        return (address(this), (salePrice * royaltyPercent) / 100);
    }
}
IKitten.sol 50 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;

interface IKitten {
    enum Trait {
        Background,
        Body,
        Clothes,
        Ears,
        Eyes,
        Head,
        Neck,
        Special,
        Weapon
    }

    struct Kitten {
        uint8 background;
        uint8 body;
        uint8 clothes;
        uint8 ears;
        uint8 eyes;
        uint8 head;
        uint8 neck;
        uint8 special;
        uint8 weapon;
    }

    /// ERC721-like

    function getOwner(uint256 tokenId) external view returns (address);

    function getNextTokenId() external view returns (uint256);

    /// WarKittens

    function mint(uint256 amount, address to) external payable;

    function mintCommunitySale(address to, bytes32[] calldata merkleProof) external payable;

    function reserveForGifting(uint256 amount) external;

    function giftKittens(address[] calldata addresses) external;

    function getKitten(uint256 tokenId) external view returns (Kitten memory);

    function getTrait(uint256 tokenId, Trait trait) external view returns (uint8);

    function updateTrait(uint256 tokenId, Trait trait, uint8 value) external;
}
IMetadata.sol 20 lines
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.13;

import "./IKitten.sol";

interface IMetadata {
    function getPlaceholderURI(uint256 tokenId) external view returns (string memory);

    function getTokenURI(uint256 tokenId, IKitten.Kitten calldata kitten, bool offChain)
        external
        view
        returns (string memory);

    function uploadTraits(
        uint8 trait,
        uint8[] calldata traitIds,
        string[] calldata names,
        string[] calldata images
    ) external;
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
Ownable.sol 76 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
ERC721.sol 216 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
/// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC.
abstract contract ERC721 {
    /*///////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*///////////////////////////////////////////////////////////////
                          METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*///////////////////////////////////////////////////////////////
                            ERC721 STORAGE                        
    //////////////////////////////////////////////////////////////*/

    mapping(address => uint256) public balanceOf;

    mapping(uint256 => address) public ownerOf;

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*///////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*///////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || msg.sender == getApproved[id] || isApprovedForAll[from][msg.sender],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            balanceOf[from]--;

            balanceOf[to]++;
        }

        ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*///////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            balanceOf[to]++;
        }

        ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = ownerOf[id];

        require(ownerOf[id] != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            balanceOf[owner]--;
        }

        delete ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
interface ERC721TokenReceiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4);
}
IERC20.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";
IERC165.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}
IERC2981.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be payed in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
MerkleProof.sol 60 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

Read Contract

COMMUNITY_SALE_PRICE 0xbec95107 → uint256
MAX_GIFTED_KITTENS 0xeb4ab9e8 → uint256
MAX_KITTENS 0x936bb7cd → uint256
MAX_KITTENS_PER_WALLET 0x10bf3bed → uint256
PUBLIC_SALE_PRICE 0x07e89ec0 → uint256
balanceOf 0x70a08231 → uint256
claimedFirst 0xebe35631 → bool
claimedSecond 0x37a2dbe1 → bool
communityFirstClaimMerkleRoot 0xbc3fb48c → bytes32
communitySecondClaimMerkleRoot 0xb9a7d664 → bytes32
getApproved 0x081812fc → address
getKitten 0x78f3c540 → tuple
getNextTokenId 0xcaa0f92a → uint256
getOwner 0xc41a360a → address
getTrait 0xbda66ea3 → uint8
hasShifted 0x20601b14 → bool
isApprovedForAll 0xe985e9c5 → bool
isCommunitySaleActive 0xeb4883ab → bool
isPublicSaleActive 0x1e84c413 → bool
isRevealed 0x54214f69 → bool
kittens 0xf3e64a02 → uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8, uint8
metadataOffset 0x0fdabb5a → uint256
name 0x06fdde03 → string
numGiftedKittens 0xc8e74c69 → uint256
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
publicSaleParticipants 0xf418ad8e → bool
renderer 0x8ada6b0f → address
royaltyInfo 0x2a55205a → address, uint256
royaltyPercent 0x9f67756d → uint8
specialMode 0xe6d740e2 → bool
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenCounter 0xd082e381 → uint256
tokenURI 0xc87b56dd → string
traitAliases 0x4fe209f9 → uint16
traitRarities 0x235329cc → uint16

Write Contract 26 functions

These functions modify contract state and require a wallet transaction to execute.

approve 0x095ea7b3
address spender
uint256 id
deSauce 0xd32aa21c
No parameters
giftKittens 0x0e15b76a
address[] addresses
mint 0x94bf804d
uint256 amount
address to
mintCommunitySale 0x79a617e8
address to
bytes32[] merkleProof
renounceOwnership 0x715018a6
No parameters
reserveForGifting 0x6c3a9b4a
uint256 amount
resetMetadataOffset 0x4d4018fa
No parameters
safeTransferFrom 0x42842e0e
address from
address to
uint256 id
safeTransferFrom 0xb88d4fde
address from
address to
uint256 id
bytes data
setAdmin 0x4b0bddd2
address admin
bool isAdmin
setApprovalForAll 0xa22cb465
address operator
bool approved
setFirstCommunityListMerkleRoot 0x4e86ef0c
bytes32 merkleRoot
setIsCommunitySaleActive 0x0d3cf1f2
bool _isCommunitySaleActive
setIsPublicSaleActive 0x28cad13d
bool _isPublicSaleActive
setKittenMode 0x86ee7331
uint256 tokenId
bool special
setMetadataOffset 0x45d1e4b1
uint256 offset
setRenderer 0x56d3163d
address _renderer
setRevealed 0x3bd64968
No parameters
setRoyaltyPercentage 0x9a6dee7f
uint8 percent
setSecondCommunityListMerkleRoot 0xe7b9e4af
bytes32 merkleRoot
transferFrom 0x23b872dd
address from
address to
uint256 id
transferOwnership 0xf2fde38b
address newOwner
updateTrait 0x4b655731
uint256 tokenId
uint8 trait
uint8 value
withdraw 0x3ccfd60b
No parameters
withdrawTokens 0x49df728c
address token

Recent Transactions

No transactions found for this address