Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xb8CDf9C4D795B18CD6748AF67258aDd526A8D56d
Balance 0 ETH
Nonce 1
Code Size 11983 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

11983 bytes
0x608060405234801561001057600080fd5b50600436106102275760003560e01c806378229c3611610130578063c4c39ed5116100b8578063e1d3cb551161007c578063e1d3cb5514610517578063e4a9209714610537578063e78d02801461054a578063ea2f29971461055d578063f2fde38b1461057057600080fd5b8063c4c39ed5146104ad578063c748668b146104c0578063c818c1ab146104c8578063d24f5232146104db578063dde44b891461050457600080fd5b80638da5cb5b116100ff5780638da5cb5b1461045a57806397a495f61461046b578063a886c3771461047e578063b422b78f14610487578063bd2f6eb81461049a57600080fd5b806378229c36146103e5578063821ba40e146103f857806382fa65621461040b578063898572a61461041e57600080fd5b80634b01c08b116101b35780635add59cb116101825780635add59cb1461038f5780635d6e05c1146103a357806361f64457146103b65780636a895e29146103ca578063715018a6146103dd57600080fd5b80634b01c08b146103375780634f3815d5146103405780635055fbc31461035357806354c856dc1461038657600080fd5b80631daebf56116101fa5780631daebf56146102d65780632709c7a1146102de57806335413f9b146102fe57806336222c68146103115780633c72f6b51461032457600080fd5b806308346d851461022c5780630ab9cf3a14610248578063146294cf1461025d578063150b7a021461029e575b600080fd5b610235600b5481565b6040519081526020015b60405180910390f35b61025b610256366004612887565b610583565b005b61028661026b3660046128a9565b6002602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161023f565b6102bd6102ac3660046128d7565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161023f565b61025b6107d0565b6102356102ec366004612976565b600f6020526000908152604090205481565b61025b61030c3660046129a9565b6107f9565b61025b61031f366004612a67565b610867565b61025b610332366004612a67565b610c86565b610235600e5481565b61025b61034e3660046129a9565b610ebd565b6103766103613660046128a9565b60056020526000908152604090205460ff1681565b604051901515815260200161023f565b610235600d5481565b600a5461037690600160a81b900460ff1681565b61025b6103b1366004612976565b610f27565b600a5461037690600160a01b900460ff1681565b61025b6103d83660046129a9565b610f51565b61025b611155565b61025b6103f3366004612887565b611169565b61025b610406366004612a67565b6114cf565b600954610286906001600160a01b031681565b61044561042c3660046128a9565b6007602052600090815260409020805460019091015482565b6040805192835260208301919091520161023f565b6000546001600160a01b0316610286565b61025b610479366004612887565b6118d1565b610235600c5481565b600854610286906001600160a01b031681565b61025b6104a83660046128a9565b611c41565b61025b6104bb3660046128a9565b611c4e565b61025b611de3565b61025b6104d63660046129a9565b611e0c565b6102866104e93660046128a9565b6003602052600090815260409020546001600160a01b031681565b61025b6105123660046128a9565b611e76565b6102356105253660046128a9565b60066020526000908152604090205481565b61025b610545366004612a67565b611e83565b610235610558366004612aea565b612025565b61025b61056b366004612976565b612056565b61025b61057e366004612976565b612080565b6000828152600760209081526040808320805460019091015460095483516339c5c1a760e01b81529351929591946001600160a01b03909116936339c5c1a793600480830194919283900301908290875af11580156105e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060a9190612b16565b15156001146106585760405162461bcd60e51b81526020600482015260156024820152741c995d99585b081b9bdd081858dd1a5d99481e595d605a1b60448201526064015b60405180910390fd5b6000848152600360205260409020546001600160a01b03163314806106f057506009546040516331a9108f60e11b81526004810186905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156106c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e59190612b38565b6001600160a01b0316145b61070c5760405162461bcd60e51b815260040161064f90612b55565b60008481526005602052604090205460ff161561075e5760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e4814995d99585b195960821b604482015260640161064f565b8183148061076b57508083145b6107a65760405162461bcd60e51b815260206004820152600c60248201526b77726f6e672063686f69636560a01b604482015260640161064f565b5050600091825260066020908152604080842092909255600590529020805460ff19166001179055565b6107d86120f6565b600a805460ff60a01b198116600160a01b9182900460ff1615909102179055565b600a54600160a01b900460ff166108225760405162461bcd60e51b815260040161064f90612b78565b60005b81518110156108635761085182828151811061084357610843612ba8565b602002602001015133612150565b8061085b81612bd4565b915050610825565b5050565b83838383600b54421061088c5760405162461bcd60e51b815260040161064f90612bed565b6108f582828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600c546040519092506108da915033908890602001612c18565b6040516020818303038152906040528051906020012061224b565b6109115760405162461bcd60e51b815260040161064f90612c31565b600d5484600e546109229190612c51565b11156109405760405162461bcd60e51b815260040161064f90612c69565b336000908152600f6020526040902054839061095d908690612c51565b111561097b5760405162461bcd60e51b815260040161064f90612ca0565b83600e600082825461098d9190612c51565b9091555050336000908152600f6020526040812080548692906109b1908490612c51565b909155506109c29050600289612cfb565b1580156109ce57508715155b610a1a5760405162461bcd60e51b815260206004820152601d60248201527f7175616e746974792073686f756c642062652061206d6f64756c6f2032000000604482015260640161064f565b6000610a2760028a612d0f565b905060005b81811015610c7a57600854604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015610a7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa29190612d23565b90506000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610af9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1d9190612d23565b600854600a5460405163fabdd6f160e01b81529293506001600160a01b039182169263fabdd6f192610b56921690600290600401612c18565b600060405180830381600087803b158015610b7057600080fd5b505af1158015610b84573d6000803e3d6000fd5b50506009546040516324e03ce160e21b81526001600160a01b039091169250639380f3849150610bbb903390600190600401612c18565b600060405180830381600087803b158015610bd557600080fd5b505af1158015610be9573d6000803e3d6000fd5b505050506040518060400160405280838152602001836001610c0b9190612c51565b9052600082815260076020908152604090912082518155910151600191820155600080516020612e7a8339815191529033908490610c4a908290612c51565b8442604051610c5d959493929190612d3c565b60405180910390a150508080610c7290612bd4565b915050610a2c565b50505050505050505050565b83838383600b544210610cab5760405162461bcd60e51b815260040161064f90612bed565b610cf982828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600c546040519092506108da915033908890602001612c18565b610d155760405162461bcd60e51b815260040161064f90612c31565b600d5484600e54610d269190612c51565b1115610d445760405162461bcd60e51b815260040161064f90612c69565b336000908152600f60205260409020548390610d61908690612c51565b1115610d7f5760405162461bcd60e51b815260040161064f90612ca0565b83600e6000828254610d919190612c51565b9091555050336000908152600f602052604081208054869290610db5908490612c51565b9091555050600854604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa158015610e04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e289190612d23565b60085460405163fabdd6f160e01b81529192506001600160a01b03169063fabdd6f190610e5b9030908d90600401612c18565b600060405180830381600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b5050505060005b89811015610c7a57610eab610ea58284612c51565b33612261565b80610eb581612bd4565b915050610e90565b600a54600160a01b900460ff16610ee65760405162461bcd60e51b815260040161064f90612b78565b60005b815181101561086357610f15828281518110610f0757610f07612ba8565b6020026020010151336122f1565b80610f1f81612bd4565b915050610ee9565b610f2f6120f6565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b600a54600160a01b900460ff16610f7a5760405162461bcd60e51b815260040161064f90612b78565b60005b81518110156110b0576000828281518110610f9a57610f9a612ba8565b602002602001015190506000600860009054906101000a90046001600160a01b03166001600160a01b031663baa51f86858581518110610fdc57610fdc612ba8565b60200260200101516040518263ffffffff1660e01b815260040161100291815260200190565b6020604051808303816000875af1158015611021573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110459190612b16565b9050801515600103611078573360009081526004602090815260408220805460018101825590835291200182905561109b565b61109b84848151811061108d5761108d612ba8565b60200260200101513361247c565b505080806110a890612bd4565b915050610f7d565b5033600090815260046020526040902054156111525760085433600081815260046020819052604091829020915163019199ad60e01b81526001600160a01b039094169363019199ad936111079392909101612d6a565b600060405180830381600087803b15801561112157600080fd5b505af1158015611135573d6000803e3d6000fd5b505033600090815260046020526040812061115293509150612855565b50565b61115d6120f6565b611167600061256b565b565b600a5482908290600160a81b900460ff166111965760405162461bcd60e51b815260040161064f90612b78565b6008546040516331a9108f60e11b81526004810184905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156111df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112039190612b38565b6001600160a01b0316146112295760405162461bcd60e51b815260040161064f90612dc6565b6008546040516331a9108f60e11b81526004810183905233916001600160a01b031690636352211e90602401602060405180830381865afa158015611272573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112969190612b38565b6001600160a01b0316146112bc5760405162461bcd60e51b815260040161064f90612dc6565b600854600a546040516323b872dd60e01b81526001600160a01b03928316926323b872dd926112f5923392909116908990600401612df5565b600060405180830381600087803b15801561130f57600080fd5b505af1158015611323573d6000803e3d6000fd5b5050600854600a546040516323b872dd60e01b81526001600160a01b0392831694506323b872dd935061135e92339216908890600401612df5565b600060405180830381600087803b15801561137857600080fd5b505af115801561138c573d6000803e3d6000fd5b505050506000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114099190612d23565b6009546040516324e03ce160e21b81529192506001600160a01b031690639380f3849061143d903390600190600401612c18565b600060405180830381600087803b15801561145757600080fd5b505af115801561146b573d6000803e3d6000fd5b505060408051808201825288815260208082018981526000878152600790925290839020915182555160019091015551600080516020612e7a83398151915292506114c0915033908890889086904290612d3c565b60405180910390a15050505050565b83838383600b5442106114f45760405162461bcd60e51b815260040161064f90612bed565b61154282828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600c546040519092506108da915033908890602001612c18565b61155e5760405162461bcd60e51b815260040161064f90612c31565b600d5484600e5461156f9190612c51565b111561158d5760405162461bcd60e51b815260040161064f90612c69565b336000908152600f602052604090205483906115aa908690612c51565b11156115c85760405162461bcd60e51b815260040161064f90612ca0565b83600e60008282546115da9190612c51565b9091555050336000908152600f6020526040812080548692906115fe908490612c51565b9091555061160f9050600289612cfb565b15801561161b57508715155b6116675760405162461bcd60e51b815260206004820152601d60248201527f7175616e746974792073686f756c642062652061206d6f64756c6f2032000000604482015260640161064f565b600061167460028a612d0f565b905060005b81811015610c7a57600854604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd9160048083019260209291908290030181865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190612d23565b90506000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176a9190612d23565b600854600a5460405163fabdd6f160e01b81529293506001600160a01b039182169263fabdd6f1926117a3921690600290600401612c18565b600060405180830381600087803b1580156117bd57600080fd5b505af11580156117d1573d6000803e3d6000fd5b50506009546040516324e03ce160e21b81526001600160a01b039091169250639380f3849150611808903090600190600401612c18565b600060405180830381600087803b15801561182257600080fd5b505af1158015611836573d6000803e3d6000fd5b5050505060405180604001604052808381526020018360016118589190612c51565b9052600082815260076020908152604090912082518155910151600191820155600080516020612e7a8339815191529033908490611897908290612c51565b84426040516118aa959493929190612d3c565b60405180910390a16118bc81336125bb565b505080806118c990612bd4565b915050611679565b600a5482908290600160a81b900460ff166118fe5760405162461bcd60e51b815260040161064f90612b78565b6008546040516331a9108f60e11b81526004810184905233916001600160a01b031690636352211e90602401602060405180830381865afa158015611947573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061196b9190612b38565b6001600160a01b0316146119915760405162461bcd60e51b815260040161064f90612dc6565b6008546040516331a9108f60e11b81526004810183905233916001600160a01b031690636352211e90602401602060405180830381865afa1580156119da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119fe9190612b38565b6001600160a01b031614611a245760405162461bcd60e51b815260040161064f90612dc6565b600854600a546040516323b872dd60e01b81526001600160a01b03928316926323b872dd92611a5d923392909116908990600401612df5565b600060405180830381600087803b158015611a7757600080fd5b505af1158015611a8b573d6000803e3d6000fd5b5050600854600a546040516323b872dd60e01b81526001600160a01b0392831694506323b872dd9350611ac692339216908890600401612df5565b600060405180830381600087803b158015611ae057600080fd5b505af1158015611af4573d6000803e3d6000fd5b505050506000600960009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190612d23565b6009546040516324e03ce160e21b81529192506001600160a01b031690639380f38490611ba5903090600190600401612c18565b600060405180830381600087803b158015611bbf57600080fd5b505af1158015611bd3573d6000803e3d6000fd5b505060408051808201825288815260208082018981526000878152600790925290839020915182555160019091015551600080516020612e7a8339815191529250611c28915033908890889086904290612d3c565b60405180910390a1611c3a81336125bb565b5050505050565b611c496120f6565b600b55565b611c566120f6565b600e548111611ca05760405162461bcd60e51b81526020600482015260166024820152751cdd5c1c1b1e481b5a5b9a5b5d5b481c995858da195960521b604482015260640161064f565b600860009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190612d23565b600860009054906101000a90046001600160a01b03166001600160a01b03166332cb6b0c6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611d6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d909190612d23565b611d9a9190612e19565b811115611dde5760405162461bcd60e51b815260206004820152601260248201527113585e081cdd5c1c1b1e481c995858da195960721b604482015260640161064f565b600d55565b611deb6120f6565b600a805460ff60a81b198116600160a81b9182900460ff1615909102179055565b600a54600160a01b900460ff16611e355760405162461bcd60e51b815260040161064f90612b78565b60005b815181101561086357611e64828281518110611e5657611e56612ba8565b60200260200101513361264b565b80611e6e81612bd4565b915050611e38565b611e7e6120f6565b600c55565b83838383600b544210611ea85760405162461bcd60e51b815260040161064f90612bed565b611ef682828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600c546040519092506108da915033908890602001612c18565b611f125760405162461bcd60e51b815260040161064f90612c31565b600d5484600e54611f239190612c51565b1115611f415760405162461bcd60e51b815260040161064f90612c69565b336000908152600f60205260409020548390611f5e908690612c51565b1115611f7c5760405162461bcd60e51b815260040161064f90612ca0565b83600e6000828254611f8e9190612c51565b9091555050336000908152600f602052604081208054869290611fb2908490612c51565b909155505060085460405163fabdd6f160e01b81526001600160a01b039091169063fabdd6f190611fe99033908c90600401612c18565b600060405180830381600087803b15801561200357600080fd5b505af1158015612017573d6000803e3d6000fd5b505050505050505050505050565b6004602052816000526040600020818154811061204157600080fd5b90600052602060002001600091509150505481565b61205e6120f6565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6120886120f6565b6001600160a01b0381166120ed5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161064f565b6111528161256b565b6000546001600160a01b031633146111675760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161064f565b6000828152600360205260409020546001600160a01b038281169116146121895760405162461bcd60e51b815260040161064f90612b55565b6009546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906121bd90309085908790600401612df5565b600060405180830381600087803b1580156121d757600080fd5b505af11580156121eb573d6000803e3d6000fd5b5050506000838152600360205260409081902080546001600160a01b0319169055517f85a4ac7589d168612b4018473a963c60421315d02eeb9ad728db7d818d477b5d915061223f90839085904290612e30565b60405180910390a15050565b60008261225885846127d6565b14949350505050565b6000828152600260205260409020546001600160a01b0316156122965760405162461bcd60e51b815260040161064f90612e51565b6000828152600260205260409081902080546001600160a01b0319166001600160a01b038416179055517fd5116130669483bb404f94eecc4c00b3fcecbbd962841e5c130f4becc5b3355f9061223f90839085904290612e30565b6008546040516331a9108f60e11b8152600481018490526001600160a01b03838116921690636352211e90602401602060405180830381865afa15801561233c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123609190612b38565b6001600160a01b0316146123865760405162461bcd60e51b815260040161064f90612b55565b6000828152600260205260409020546001600160a01b0316156123bb5760405162461bcd60e51b815260040161064f90612e51565b6008546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906123ef90849030908790600401612df5565b600060405180830381600087803b15801561240957600080fd5b505af115801561241d573d6000803e3d6000fd5b5050506000838152600260205260409081902080546001600160a01b0319166001600160a01b038516179055517fd5116130669483bb404f94eecc4c00b3fcecbbd962841e5c130f4becc5b3355f915061223f90839085904290612e30565b6000828152600260205260409020546001600160a01b038281169116146124b55760405162461bcd60e51b815260040161064f90612b55565b6008546040516323b872dd60e01b81526001600160a01b03909116906323b872dd906124e990309085908790600401612df5565b600060405180830381600087803b15801561250357600080fd5b505af1158015612517573d6000803e3d6000fd5b5050506000838152600260205260409081902080546001600160a01b0319169055517f2e0aadfdcc1b375405c7f7e9c66f661756d90fe8a6fe4a0a182b77e45fc0886e915061223f90839085904290612e30565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000828152600360205260409020546001600160a01b0316156125f05760405162461bcd60e51b815260040161064f90612e51565b6000828152600360205260409081902080546001600160a01b0319166001600160a01b038416179055517fe71a1073082ff4f09b6b629f64fc0273be705be91a45916c2666d38ccbad4c0d9061223f90839085904290612e30565b6009546040516331a9108f60e11b8152600481018490526001600160a01b03838116921690636352211e90602401602060405180830381865afa158015612696573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ba9190612b38565b6001600160a01b0316146126e05760405162461bcd60e51b815260040161064f90612b55565b6000828152600360205260409020546001600160a01b0316156127155760405162461bcd60e51b815260040161064f90612e51565b6009546040516323b872dd60e01b81526001600160a01b03909116906323b872dd9061274990849030908790600401612df5565b600060405180830381600087803b15801561276357600080fd5b505af1158015612777573d6000803e3d6000fd5b5050506000838152600360205260409081902080546001600160a01b0319166001600160a01b038516179055517fe71a1073082ff4f09b6b629f64fc0273be705be91a45916c2666d38ccbad4c0d915061223f90839085904290612e30565b600081815b845181101561281b57612807828683815181106127fa576127fa612ba8565b6020026020010151612823565b91508061281381612bd4565b9150506127db565b509392505050565b600081831061283f57600082815260208490526040902061284e565b60008381526020839052604090205b9392505050565b508054600082559060005260206000209081019061115291905b80821115612883576000815560010161286f565b5090565b6000806040838503121561289a57600080fd5b50508035926020909101359150565b6000602082840312156128bb57600080fd5b5035919050565b6001600160a01b038116811461115257600080fd5b6000806000806000608086880312156128ef57600080fd5b85356128fa816128c2565b9450602086013561290a816128c2565b935060408601359250606086013567ffffffffffffffff8082111561292e57600080fd5b818801915088601f83011261294257600080fd5b81358181111561295157600080fd5b89602082850101111561296357600080fd5b9699959850939650602001949392505050565b60006020828403121561298857600080fd5b813561284e816128c2565b634e487b7160e01b600052604160045260246000fd5b600060208083850312156129bc57600080fd5b823567ffffffffffffffff808211156129d457600080fd5b818501915085601f8301126129e857600080fd5b8135818111156129fa576129fa612993565b8060051b604051601f19603f83011681018181108582111715612a1f57612a1f612993565b604052918252848201925083810185019188831115612a3d57600080fd5b938501935b82851015612a5b57843584529385019392850192612a42565b98975050505050505050565b60008060008060608587031215612a7d57600080fd5b8435935060208501359250604085013567ffffffffffffffff80821115612aa357600080fd5b818701915087601f830112612ab757600080fd5b813581811115612ac657600080fd5b8860208260051b8501011115612adb57600080fd5b95989497505060200194505050565b60008060408385031215612afd57600080fd5b8235612b08816128c2565b946020939093013593505050565b600060208284031215612b2857600080fd5b8151801515811461284e57600080fd5b600060208284031215612b4a57600080fd5b815161284e816128c2565b6020808252600990820152683737ba1037bbb732b960b91b604082015260600190565b602080825260169082015275436f6e7472616374206973206e6f742061637469766560501b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612be657612be6612bbe565b5060010190565b602080825260119082015270233932b29036b4b73a1034b99037bb32b960791b604082015260600190565b6001600160a01b03929092168252602082015260400190565b60208082526006908201526510b83937b7b360d11b604082015260600190565b60008219821115612c6457612c64612bbe565b500190565b6020808252601b908201527f4d617820737570706c7920667265656d696e7420726561636865640000000000604082015260600190565b60208082526025908201527f4e6f7420616c6c6f77656420746f20667265656d696e742074686973207175616040820152646e7469747960d81b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b600082612d0a57612d0a612ce5565b500690565b600082612d1e57612d1e612ce5565b500490565b600060208284031215612d3557600080fd5b5051919050565b6001600160a01b03959095168552602085019390935260408401919091526060830152608082015260a00190565b6000604082016040835280855480835260608501915086600052602092508260002060005b82811015612dab57815484529284019260019182019101612d8f565b5050506001600160a01b039490941692019190915250919050565b6020808252601590820152742cb7ba9036bab9ba1037bbb7103a34329027232a1760591b604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082821015612e2b57612e2b612bbe565b500390565b6001600160a01b039390931683526020830191909152604082015260600190565b6020808252600e908201526d105b1c9958591e481cdd185ad95960921b60408201526060019056fe8f9b65c4201143c15e345350ae2fbcb591a753d71eb2a62b3f804db0d26c242ca2646970667358221220746e68aa58f6d0935fa4f5cd55bb0dcf9d8c6bf19e055b304d05609fda125b7b64736f6c634300080e0033

Verified Source Code Partial Match

Compiler: v0.8.14+commit.80d49f37 EVM: london Optimization: Yes (200 runs)
OperatorContract.sol 1137 lines
// File: @openzeppelin/contracts/utils/Context.sol


// 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;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @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 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 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);
    }
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree 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.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 */
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 Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle 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++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`,
     * consuming from one or the other at each step according to the instructions given by
     * `proofFlags`.
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            return hashes[totalHashes - 1];
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

// File: erc721a/contracts/IERC721A.sol


// ERC721A Contracts v4.2.3
// Creator: Chiru Labs

pragma solidity ^0.8.4;

/**
 * @dev Interface of ERC721A.
 */
interface IERC721A {
    /**
     * 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();

    // =============================================================
    //                            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);
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: contracts/2_Owner.sol


pragma solidity ^0.8.14;






interface IX2 {
    function mintByOperator(address _addressBuyer, uint _quantity) external ;
    function ownerOf(uint tokenId) external view returns (address owner);
    function totalSupply() external view returns (uint);
    function revealActive() external returns(bool);
}

interface IX1 {
    function mintBySaleContract(address _addressBuyer, uint _quantity) external ;
    function ownerOf(uint tokenId) external view returns (address owner);
    function totalSupply() external view returns (uint);
    function MAX_SUPPLY() external returns (uint);
    function unstakeNFT(uint[] memory tokenId, address _to) external;
    function isStaked(uint) external returns(bool);
}

  library StructLib {
    struct Parent {
        uint tokenId1;
        uint tokenId2;
    }
}


contract OperatorContract is Ownable, ReentrancyGuard {

    event X1Staked(address owner, uint256 tokenId, uint256 timeframe);
    event X1Unstaked(address owner, uint256 tokenId, uint256 timeframe);
    event X2Staked(address owner, uint256 tokenId, uint256 timeframe);
    event X2Unstaked(address owner, uint256 tokenId, uint256 timeframe);
    event Merged(address owner, uint256 tokenId1, uint tokenId2, uint createdTokenId, uint256 timeframe);

    mapping(uint => address) public X1Depositaries;
    mapping(uint => address) public X2Depositaries;
    mapping(address => uint[]) public tokenIdOldStaking;

     // mapping to check if given id is revealed
    mapping(uint => bool) public isRevealed;
    // mapping to get the chosen parentID to attribute revealed metadata
    mapping(uint => uint) public chosenMainTokenId;

    mapping(uint => StructLib.Parent) public parents;

    address public X1Address;
    address public X2Address;

    address burnAddress = 0x000000000000000000000000000000000000dEaD;

    // activation
    bool public isStakingActive;
    bool public isMergeActive;
    uint public freeMintLimit;

    // free mint root
    bytes32 public freeMintRoot;

    // free mint supply
    uint public maxSupplyFreeMint = 1500;
    uint public countMintedByFreeMint;

    // Mapping to follow the freemint used
   mapping(address => uint) public freeMintsUsed;

    modifier stakingIsActive() {
        require(isStakingActive, "Contract is not active");
        _;
    }

     modifier mergeCheck(uint256 _tokenId1,uint256 _tokenId2) {
        require(isMergeActive, "Contract is not active");
        require(IERC721A(X1Address).ownerOf(_tokenId1) == msg.sender, "You must own the NFT.");
        require(IERC721A(X1Address).ownerOf(_tokenId2) == msg.sender, "You must own the NFT.");
        _;
    }

    modifier freeMintCheck(uint _quantity, uint count, bytes32[] calldata proof){
        require(block.timestamp < freeMintLimit, "Free mint is over");
        require(MerkleProof.verify(proof, freeMintRoot, keccak256(abi.encode(msg.sender, count))), "!proof");
        require(countMintedByFreeMint + _quantity <= maxSupplyFreeMint , 'Max supply freemint reached');
        require(freeMintsUsed[msg.sender] + _quantity <= count, 'Not allowed to freemint this quantity');
        countMintedByFreeMint += _quantity;
        freeMintsUsed[msg.sender] += _quantity;
        _;
    }

    constructor(address oxyaAddress_, address X2Address_) {
        X1Address = oxyaAddress_;
        X2Address = X2Address_;
    }

  
      /**
     * @dev Merge 2 tokens in the X1 contract to get 1 X2 token
     * @param _tokenId1 ids of token X1
     * @param _tokenId2 ids of token X2
     */
    function Merge(uint _tokenId1,uint _tokenId2) public mergeCheck(_tokenId1, _tokenId2)  {
        IERC721A(X1Address).transferFrom(msg.sender, burnAddress, _tokenId1);
        IERC721A(X1Address).transferFrom(msg.sender, burnAddress, _tokenId2);

        uint totalSupply = IX2(X2Address).totalSupply();
        IX2(X2Address).mintByOperator(msg.sender, 1);
         parents[totalSupply] = StructLib.Parent(
                _tokenId1,
                _tokenId2
            );
        emit Merged(msg.sender, _tokenId1, _tokenId2, totalSupply, block.timestamp);
    }

    /**
     * @dev Merge 2 tokens in the X1 contract to get 1 X2 token and stake it in present operator contrat
     * @param _tokenId1 ids of token X1
     * @param _tokenId2 ids of token X2
     */
    function MergeAndStake(uint256 _tokenId1, uint256 _tokenId2) public  mergeCheck(_tokenId1, _tokenId2) {
        IERC721A(X1Address).transferFrom(msg.sender, burnAddress, _tokenId1);
        IERC721A(X1Address).transferFrom(msg.sender, burnAddress, _tokenId2);
        
        uint totalSupply = IX2(X2Address).totalSupply();
        IX2(X2Address).mintByOperator(address(this), 1);
         parents[totalSupply] = StructLib.Parent(
                _tokenId1,
                _tokenId2
            );
        emit Merged(msg.sender, _tokenId1, _tokenId2, totalSupply, block.timestamp);

        stakeFreeMintX2NFT(totalSupply, msg.sender);
    }

    
      /**
     * @dev  Function to mint freeMints X1
     * @param _quantity quantity of token X1 to mint
     * @param count maximum of authorized mint for the msg.sender
     * @param proof merkle proof
     */
    function freeMintX1(uint _quantity, uint count, bytes32[] calldata proof) external freeMintCheck(_quantity, count, proof) {

        IX1(X1Address).mintBySaleContract(msg.sender, _quantity);  
    }

   /**
     * @dev  Function to mint and stake freeMints X1
     * @param _quantity quantity of token X1 to mint
     * @param count maximum of authorized mint for the msg.sender
     * @param proof merkle proof
     */
    function freeMintX1Stake(uint _quantity, uint count, bytes32[] calldata proof) external freeMintCheck(_quantity, count, proof) {

        uint totalSupply = IX1(X1Address).totalSupply();
        IX1(X1Address).mintBySaleContract(address(this), _quantity);  

        for(uint i=0; i<_quantity; i++){
            stakeFreeMintX1NFT(totalSupply + i, msg.sender);
        }
    }

      /**
     * @dev  Function to mint X1 and merge into X2
     * @param _quantity quantity of token X1 to mint
     * @param count maximum of authorized mint for the msg.sender
     * @param proof merkle proof
     */
    function freeMintX2( uint _quantity, uint count, bytes32[] calldata proof) external freeMintCheck(_quantity, count, proof) {
        require(_quantity % 2 == 0 && _quantity != 0 , "quantity should be a modulo 2");
        uint allowableMints = _quantity/2;

        for(uint i; i < allowableMints; i++ ){
             uint totalSupplyX1 = IX1(X1Address).totalSupply();
            uint totalSupplyX2 = IX2(X2Address).totalSupply();
            IX1(X1Address).mintBySaleContract(burnAddress, 2);  
            IX2(X2Address).mintByOperator(msg.sender, 1);
            parents[totalSupplyX2] = StructLib.Parent(
                    totalSupplyX1 ,
                    totalSupplyX1 +  1
                );
            emit Merged(msg.sender, totalSupplyX1 , totalSupplyX1 + 1, totalSupplyX2 , block.timestamp);
        }
    }

      /**
     * @dev  Function to mint X1 and merge and stake into X2
     * @param _quantity quantity of token X1 to mint
     * @param count maximum of authorized mint for the msg.sender
     * @param proof merkle proof
     */
    function freeMintX2Stake(uint _quantity, uint count, bytes32[] calldata proof) external  freeMintCheck(_quantity, count, proof){
        require(_quantity % 2 == 0 && _quantity != 0 , "quantity should be a modulo 2");
        uint allowableMints = _quantity/2;

        for(uint i; i < allowableMints; i++ ){
            uint totalSupplyX1 = IX1(X1Address).totalSupply();
            uint totalSupplyX2 = IX2(X2Address).totalSupply();
            IX1(X1Address).mintBySaleContract(burnAddress, 2);  

            IX2(X2Address).mintByOperator(address(this), 1);
            parents[totalSupplyX2] = StructLib.Parent(
                    totalSupplyX1,
                    totalSupplyX1 + 1
                );
            emit Merged(msg.sender, totalSupplyX1, totalSupplyX1 + 1, totalSupplyX2, block.timestamp);

            stakeFreeMintX2NFT(totalSupplyX2, msg.sender);
        }
    }

    //STAKING X2 NFT
    /**
     * @dev stake tokens X2  in the contract
     * @param _tokenId ids of token
     * @param _to address of staker
     */
    function stakeX2NFT(uint256 _tokenId, address _to) internal  {
        require(IX2(X2Address).ownerOf(_tokenId) == _to, "not owner");
        require(X2Depositaries[_tokenId] == address(0), "Already staked");
           
        IERC721A(X2Address).transferFrom(_to, address(this), _tokenId); 
        X2Depositaries[_tokenId] = _to;
        
        emit X2Staked(_to, _tokenId, block.timestamp);
    }

    /**
     * @dev stake tokens X2 in the contract, called by freeMint function
     * @param _tokenId ids of token
     * @param _to address of staker
     */
    function stakeFreeMintX2NFT(uint256 _tokenId, address _to) internal  {
        require(X2Depositaries[_tokenId] == address(0), "Already staked");

        X2Depositaries[_tokenId] = _to;
        
        emit X2Staked(_to, _tokenId, block.timestamp);
    }

     /**
     * @dev stake multiple tokens X2 in the contract
     * @param _tokenIds ids of tokens
     */
    function batchStakeX2NFT(uint256[] memory _tokenIds) public stakingIsActive {
        for (uint256 i = 0; i < _tokenIds.length; i++) {
            stakeX2NFT(_tokenIds[i], msg.sender);
        }
    }

    /**
     * @dev unstake token X2 out of the contract
     * @param _tokenId tokenId of token to unstake
      * @param _to address of unstaker
     */
    function unstakeX2NFT(uint256 _tokenId, address _to) internal {
        require(X2Depositaries[_tokenId] == _to, "not owner");
        
        IERC721A(X2Address).transferFrom(address(this), _to, _tokenId); 
        X2Depositaries[_tokenId] = address(0);

        emit X2Unstaked(_to, _tokenId, block.timestamp);
    }

     /**
     * @dev unstake multiple token X2 out of the contract
     * @param _tokenIds tokenId of token to unstake
     */
    function batchUnstakeX2NFT(uint256[] memory _tokenIds) public stakingIsActive {
        for (uint256 i = 0; i < _tokenIds.length; i++) {
            unstakeX2NFT(_tokenIds[i], msg.sender);
        }
    }

    // STAKING X1 NFT
    /**
     * @dev stake tokens X1  in the contract
     * @param _tokenId ids of token
     * @param _to address of staker
     */
    function stakeX1NFT(uint256 _tokenId, address _to) internal  {
        require(IX1(X1Address).ownerOf(_tokenId) == _to, "not owner");
        require(X1Depositaries[_tokenId] == address(0), "Already staked");
           
        IERC721A(X1Address).transferFrom(_to, address(this), _tokenId); 
        X1Depositaries[_tokenId] = _to;
        
        emit X1Staked(_to, _tokenId, block.timestamp);
    }

    /**
     * @dev stake tokens X1  in the contract, callable by freeMint
     * @param _tokenId ids of token
     * @param _to address of staker
     */
    function stakeFreeMintX1NFT(uint256 _tokenId, address _to) internal  {
        require(X1Depositaries[_tokenId] == address(0), "Already staked");

        X1Depositaries[_tokenId] = _to;
        
        emit X1Staked(_to, _tokenId, block.timestamp);
    }

     /**
     * @dev stake multiple tokens X1  in the contract
     * @param _tokenIds ids of token
     */
    function batchStakeX1NFT(uint256[] memory _tokenIds) public stakingIsActive {
        for (uint256 i = 0; i < _tokenIds.length; i++) {
            stakeX1NFT(_tokenIds[i], msg.sender);
        }
    }

    // UNSTAKE X1 NFT
      /**
     * @dev unstake token X1 out of the contract
     * @param _tokenId tokenId of token to unstake
      * @param _to address of unstaker
     */
    function unstakeX1NFT(uint256 _tokenId, address _to) internal {
        require(X1Depositaries[_tokenId] == _to, "not owner");
        
        IERC721A(X1Address).transferFrom(address(this), _to, _tokenId); 

        X1Depositaries[_tokenId] = address(0);

        emit X1Unstaked(_to, _tokenId, block.timestamp);
    }

     /**
     * @dev unstake token X1 out of the contract, also check the staking in previous contract
     * @param _tokenIds tokenIds of token to unstake
     */
    function batchUnstakeX1NFT(uint256[] memory _tokenIds) public stakingIsActive {
      
       for (uint256 i = 0; i < _tokenIds.length; i++) {
            uint256 value = _tokenIds[i];
            bool isStakedInX1 = IX1(X1Address).isStaked(_tokenIds[i]);

            if(isStakedInX1 == true){
                tokenIdOldStaking[msg.sender].push(value);
            } else {
                unstakeX1NFT(_tokenIds[i], msg.sender);
            }
        }
       
        if(tokenIdOldStaking[msg.sender].length > 0){
            IX1(X1Address).unstakeNFT(tokenIdOldStaking[msg.sender], msg.sender);
                delete tokenIdOldStaking[msg.sender];
         }
    }

      /**
     * @dev reveal selected NFT with the parent choice for the metadata
     * @param _tokenId id of token to reveal
     * @param parentChoice id of token Parent for metadata attribution
     */
    function revealNFT(uint _tokenId, uint parentChoice ) public  {
        uint idParent1 = parents[_tokenId].tokenId1;
        uint idParent2 =parents[_tokenId].tokenId2;
        require(IX2(X2Address).revealActive() == true, "reveal not active yet");
        require(X2Depositaries[_tokenId] == msg.sender || IX2(X2Address).ownerOf(_tokenId) == msg.sender , "not owner");
        require(isRevealed[_tokenId] == false, "already Revealed");
        require(parentChoice == idParent1 || parentChoice == idParent2, "wrong choice" );
        chosenMainTokenId[_tokenId] = parentChoice;
        isRevealed[_tokenId] = true;
    }

    /**
     * @dev necessary to transfer tokens
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external pure returns (bytes4) {
        return IERC721Receiver.onERC721Received.selector;
    }

    /**
     * @dev necessary to calculate proof
     * @param _root root for free mint
     */
    function setFreeMintMerkleRoot(bytes32 _root) public onlyOwner {
        freeMintRoot = _root;
    }

    /**
     * @dev timestamp to activate freeMint
     * @param timestamp timestamp limit for freemint
     */
    function setFreeMintLimit(uint timestamp) external onlyOwner {
        freeMintLimit = timestamp;
    }

     function setIsMergeActive() external onlyOwner {
        isMergeActive = !isMergeActive;
    }

    function setIsStakingActive() external onlyOwner {
        isStakingActive = !isStakingActive;
    }

     /*
     * FreeMint supply
     * function to change FreeMintSupply
     */
    function setFreeMintSupply(uint _newFreeMintSupply) external onlyOwner {
        require(_newFreeMintSupply > countMintedByFreeMint, "supply minimum reached");
        require(_newFreeMintSupply <= IX1(X1Address).MAX_SUPPLY() - IX1(X1Address).totalSupply(), "Max supply reached");
        maxSupplyFreeMint = _newFreeMintSupply;
    }

    // MIGRATION ONLY.
    function setX1Contract(address X1Contract) public onlyOwner {
        X1Address = X1Contract;
    }

      function setX2Contract(address X2Contract) public onlyOwner {
        X2Address = X2Contract;
    }

}

Read Contract

X1Address 0xb422b78f → address
X1Depositaries 0x146294cf → address
X2Address 0x82fa6562 → address
X2Depositaries 0xd24f5232 → address
chosenMainTokenId 0xe1d3cb55 → uint256
countMintedByFreeMint 0x4b01c08b → uint256
freeMintLimit 0x08346d85 → uint256
freeMintRoot 0xa886c377 → bytes32
freeMintsUsed 0x2709c7a1 → uint256
isMergeActive 0x5add59cb → bool
isRevealed 0x5055fbc3 → bool
isStakingActive 0x61f64457 → bool
maxSupplyFreeMint 0x54c856dc → uint256
onERC721Received 0x150b7a02 → bytes4
owner 0x8da5cb5b → address
parents 0x898572a6 → uint256, uint256
tokenIdOldStaking 0xe78d0280 → uint256

Write Contract 20 functions

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

Merge 0x78229c36
uint256 _tokenId1
uint256 _tokenId2
MergeAndStake 0x97a495f6
uint256 _tokenId1
uint256 _tokenId2
batchStakeX1NFT 0x4f3815d5
uint256[] _tokenIds
batchStakeX2NFT 0xc818c1ab
uint256[] _tokenIds
batchUnstakeX1NFT 0x6a895e29
uint256[] _tokenIds
batchUnstakeX2NFT 0x35413f9b
uint256[] _tokenIds
freeMintX1 0xe4a92097
uint256 _quantity
uint256 count
bytes32[] proof
freeMintX1Stake 0x3c72f6b5
uint256 _quantity
uint256 count
bytes32[] proof
freeMintX2 0x36222c68
uint256 _quantity
uint256 count
bytes32[] proof
freeMintX2Stake 0x821ba40e
uint256 _quantity
uint256 count
bytes32[] proof
renounceOwnership 0x715018a6
No parameters
revealNFT 0x0ab9cf3a
uint256 _tokenId
uint256 parentChoice
setFreeMintLimit 0xbd2f6eb8
uint256 timestamp
setFreeMintMerkleRoot 0xdde44b89
bytes32 _root
setFreeMintSupply 0xc4c39ed5
uint256 _newFreeMintSupply
setIsMergeActive 0xc748668b
No parameters
setIsStakingActive 0x1daebf56
No parameters
setX1Contract 0x5d6e05c1
address X1Contract
setX2Contract 0xea2f2997
address X2Contract
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address