Address Contract Partially Verified
Address
0xa6Ec49E06C25F63292bac1Abc1896451A0f4cFB7
Balance
0 ETH
Nonce
1
Code Size
12055 bytes
Creator
0xDb80F3db...0B04 at tx 0xcd3b6e80...8d1f23
Indexed Transactions
0
Contract Bytecode
12055 bytes
0x6080604052600436106104265760003560e01c806388993c8111610229578063b0cfbf161161012e578063dd62ed3e116100b6578063f2fde38b1161007a578063f2fde38b14610be9578063f623bb8b14610c09578063f82fa75614610c1f578063f8c0fd2014610c3c578063fbbf8cc314610c5157600080fd5b8063dd62ed3e14610b4f578063dfdedf6914610b6f578063e58306f914610b8f578063e6c6990a14610baf578063e757223014610bc957600080fd5b8063c3cb97c6116100fd578063c3cb97c614610abc578063c6ee6e3514610adc578063cacf084214610aef578063d266f3a914610b0f578063d83ae33214610b2f57600080fd5b8063b0cfbf1614610a47578063b6a3f59a14610a67578063b94b237614610a87578063c326876814610a9c57600080fd5b8063a1af10ca116101b1578063a9059cbb11610180578063a9059cbb146109bf578063a91bd1a9146109df578063ad1203dc146109ff578063af54001e14610a12578063afb16d1814610a2757600080fd5b8063a1af10ca1461093f578063a1db97821461095f578063a457c2d71461097f578063a7593fb71461099f57600080fd5b80638da5cb5b116101f85780638da5cb5b146108b75780638f770ad0146108d557806391b7f5ed146108ea57806395d89b411461090a57806398ad44171461091f57600080fd5b806388993c8114610857578063891bbe731461086c57806389f26d581461088c5780638d859f3e146108a157600080fd5b80634070a0c91161032f578063627255df116102b757806379ab3c891161028657806379ab3c89146107c057806379cc6790146107d55780637fb8c6d3146107f5578063853828b61461082d57806387491c601461084257600080fd5b8063627255df146107405780636d3de8061461076057806370a0823114610775578063715018a6146107ab57600080fd5b8063464c3428116102fe578063464c3428146106be57806346f41ed5146106de5780634783f0ef146106f85780634c23ce91146107185780635e8306561461072d57600080fd5b80634070a0c91461064957806342966c681461066957806343696f181461068957806345f7e06e146106a957600080fd5b806328ff1b51116103b2578063330067861161038157806333006786146105be57806334d00766146105de57806339509351146105f35780633d3f9c57146106135780633e07311c1461063357600080fd5b806328ff1b511461054c5780632b26a6bf1461056c5780632eb4a7ab1461058c578063313ce567146105a257600080fd5b80631963d0cc116103f95780631963d0cc146104c557806320fab142146104dd5780632181384e146104f757806323b872dd1461050c578063286c81371461052c57600080fd5b806306fdde031461042b5780630825850a14610456578063095ea7b31461048657806318160ddd146104a6575b600080fd5b34801561043757600080fd5b50610440610c87565b60405161044d9190612890565b60405180910390f35b34801561046257600080fd5b50610476610471366004612901565b610d19565b604051901515815260200161044d565b34801561049257600080fd5b506104766104a1366004612901565b610d66565b3480156104b257600080fd5b506002545b60405190815260200161044d565b3480156104d157600080fd5b50600a5460ff16610476565b3480156104e957600080fd5b506007546104769060ff1681565b61050a610505366004612977565b610d7e565b005b34801561051857600080fd5b506104766105273660046129e6565b6110d8565b34801561053857600080fd5b506104b7610547366004612a22565b6110fc565b34801561055857600080fd5b5061050a610567366004612b18565b61111d565b34801561057857600080fd5b5061050a610587366004612a22565b61116c565b34801561059857600080fd5b506104b7600f5481565b3480156105ae57600080fd5b506040516012815260200161044d565b3480156105ca57600080fd5b506104766105d9366004612bd3565b611179565b3480156105ea57600080fd5b50600b546104b7565b3480156105ff57600080fd5b5061047661060e366004612901565b611220565b34801561061f57600080fd5b5061047661062e366004612c26565b611242565b34801561063f57600080fd5b506104b760155481565b34801561065557600080fd5b5061050a610664366004612a22565b611265565b34801561067557600080fd5b5061050a610684366004612a22565b611272565b34801561069557600080fd5b5061050a6106a4366004612c26565b61127f565b3480156106b557600080fd5b5061050a6112f9565b3480156106ca57600080fd5b5061050a6106d9366004612c26565b611313565b3480156106ea57600080fd5b506016546104769060ff1681565b34801561070457600080fd5b5061050a610713366004612a22565b61133f565b34801561072457600080fd5b5061047661136f565b61050a61073b366004612901565b611397565b34801561074c57600080fd5b5061047661075b366004612a22565b6114c4565b34801561076c57600080fd5b5061050a6114e7565b34801561078157600080fd5b506104b7610790366004612c26565b6001600160a01b031660009081526020819052604090205490565b3480156107b757600080fd5b5061050a6114fb565b3480156107cc57600080fd5b5061050a61150f565b3480156107e157600080fd5b5061050a6107f0366004612901565b611526565b34801561080157600080fd5b50601354610815906001600160a01b031681565b6040516001600160a01b03909116815260200161044d565b34801561083957600080fd5b5061050a61153b565b34801561084e57600080fd5b5061050a61156a565b34801561086357600080fd5b50610476611580565b34801561087857600080fd5b50610815610887366004612a22565b6115a6565b34801561089857600080fd5b5061050a6115d0565b3480156108ad57600080fd5b506104b7600d5481565b3480156108c357600080fd5b506005546001600160a01b0316610815565b3480156108e157600080fd5b506104b76115e7565b3480156108f657600080fd5b5061050a610905366004612a22565b611602565b34801561091657600080fd5b5061044061160f565b34801561092b57600080fd5b5061050a61093a366004612c4f565b61161e565b34801561094b57600080fd5b5061047661095a366004612c26565b611640565b34801561096b57600080fd5b5061050a61097a366004612901565b61168d565b34801561098b57600080fd5b5061047661099a366004612901565b6117d9565b3480156109ab57600080fd5b5061050a6109ba366004612a22565b611817565b3480156109cb57600080fd5b506104766109da366004612901565b611850565b3480156109eb57600080fd5b5061050a6109fa366004612c26565b61185e565b61050a610a0d366004612c6c565b6118de565b348015610a1e57600080fd5b50600c546104b7565b348015610a3357600080fd5b5061050a610a42366004612cc6565b611a2f565b348015610a5357600080fd5b50610476610a62366004612a22565b611aa6565b348015610a7357600080fd5b5061050a610a82366004612a22565b611adf565b348015610a9357600080fd5b5061050a611b0f565b348015610aa857600080fd5b5061050a610ab7366004612c4f565b611b23565b348015610ac857600080fd5b5061050a610ad7366004612c4f565b611b3e565b61050a610aea366004612d0b565b611b59565b348015610afb57600080fd5b5061050a610b0a366004612c26565b611e89565b348015610b1b57600080fd5b506104b7610b2a366004612c26565b611eb2565b348015610b3b57600080fd5b5061050a610b4a366004612d47565b611ef9565b348015610b5b57600080fd5b506104b7610b6a366004612d86565b611f30565b348015610b7b57600080fd5b5061050a610b8a366004612c26565b611f5b565b348015610b9b57600080fd5b5061050a610baa366004612901565b611fd1565b348015610bbb57600080fd5b506010546104769060ff1681565b348015610bd557600080fd5b506104b7610be4366004612a22565b612028565b348015610bf557600080fd5b5061050a610c04366004612c26565b61208b565b348015610c1557600080fd5b506104b7600e5481565b348015610c2b57600080fd5b50600a54610100900460ff16610476565b348015610c4857600080fd5b5061050a6120c3565b348015610c5d57600080fd5b506104b7610c6c366004612c26565b6001600160a01b031660009081526009602052604090205490565b606060038054610c9690612db9565b80601f0160208091040260200160405190810160405280929190818152602001828054610cc290612db9565b8015610d0f5780601f10610ce457610100808354040283529160200191610d0f565b820191906000526020600020905b815481529060010190602001808311610cf257829003601f168201915b5050505050905090565b600a5460009060ff16610d2e57506001610d60565b600b5482610d51856001600160a01b031660009081526009602052604090205490565b610d5b9190612e0a565b111590505b92915050565b600033610d748185856120de565b5060019392505050565b610d8661136f565b610da3576040516309c7220160e31b815260040160405180910390fd5b670de0b6b3a7640000841015610dcc5760405163b562e8dd60e01b815260040160405180910390fd5b610dd7858484611179565b610df45760405163097b24df60e41b815260040160405180910390fd5b610dfd846114c4565b610e1a576040516393eeb41560e01b815260040160405180910390fd5b610e248585610d19565b610e41576040516366be767160e11b815260040160405180910390fd5b610e4a84611aa6565b610e675760405163a4875a4960e01b815260040160405180910390fd5b600e543414610e895760405163078d696560e31b815260040160405180910390fd5b610e9281611242565b610eaf57604051636c501c9960e11b815260040160405180910390fd5b600084610ebb83611eb2565b610ec59190612e22565b6040516370a0823160e01b81526001600160a01b03888116600483015291925083918391908316906370a082319060240160206040518083038186803b158015610f0e57600080fd5b505afa158015610f22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f469190612e41565b1015610f6557604051631642df1760e21b815260040160405180910390fd5b604051636eb1769f60e11b81526001600160a01b03888116600483015230602483015283919083169063dd62ed3e9060440160206040518083038186803b158015610faf57600080fd5b505afa158015610fc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe79190612e41565b10156110065760405163017e286b60e51b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b03888116600483015230602483015260448201849052600091908316906323b872dd90606401602060405180830381600087803b15801561105a57600080fd5b505af115801561106e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110929190612e5a565b9050806110b257604051633c9fd93960e21b815260040160405180910390fd5b6110ba61218d565b6110c488886121cf565b6110ce88886121f1565b5050505050505050565b6000336110e68582856122a1565b6110f18585856122e6565b506001949350505050565b6014818154811061110c57600080fd5b600091825260209091200154905081565b6111256123fe565b611131601260006127bd565b61113d601460006127bd565b81516111509060129060208501906127db565b508051611164906014906020840190612840565b505051601555565b6111746123fe565b600c55565b600f5460009061119c576040516363868c5560e11b815260040160405180910390fd5b6040516bffffffffffffffffffffffff19606086901b16602082015260009060340160405160208183030381529060405280519060200120905061121784848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050600f549150849050612489565b95945050505050565b600033610d748185856112338383611f30565b61123d9190612e0a565b6120de565b6001600160a01b031660009081526011602052604090205460ff16151560011490565b61126d6123fe565b600b55565b61127c338261249f565b50565b61128761257a565b6001600160a01b0381166112ae576040516322646a9760e21b815260040160405180910390fd5b6112b781611640565b156112d557604051638afaeb9d60e01b815260040160405180910390fd5b6001600160a01b03166000908152600660205260409020805460ff19166001179055565b6113016123fe565b6016805462ffff001916610100179055565b61131b6123fe565b6001600160a01b03166000908152601160205260409020805460ff19166001179055565b6113476123fe565b600f5481141561136a5760405163a28a88c160e01b815260040160405180910390fd5b600f55565b60165460009062010000900460ff1680156113925750601654610100900460ff16155b905090565b60165460ff16156113bb576040516306717a3b60e51b815260040160405180910390fd5b670de0b6b3a76400008110156113e45760405163b562e8dd60e01b815260040160405180910390fd5b6113ec611580565b611409576040516306717a3b60e51b815260040160405180910390fd5b611412816114c4565b61142f576040516393eeb41560e01b815260040160405180910390fd5b61143881611aa6565b6114555760405163a4875a4960e01b815260040160405180910390fd5b61145f8282610d19565b61147c576040516366be767160e11b815260040160405180910390fd5b61148581612028565b34146114a45760405163078d696560e31b815260040160405180910390fd5b6114ac61218d565b6114b682826121cf565b6114c082826121f1565b5050565b600a54600090610100900460ff166114de57506001919050565b50600c54101590565b6114ef6123fe565b6010805460ff19169055565b61150361257a565b61150d60006125d4565b565b6115176123fe565b6010805460ff19166001179055565b6115318233836122a1565b6114c0828261249f565b6115436123fe565b47611561576040516363868c5560e11b815260040160405180910390fd5b61150d47612626565b6115726123fe565b6016805462ffff0019169055565b601654600090610100900460ff16801561139257505060165462010000900460ff161590565b601281815481106115b657600080fd5b6000918252602090912001546001600160a01b0316905081565b6115d86123fe565b6016805460ff19166001179055565b60075460009060ff166115fb575060025490565b5060085490565b61160a6123fe565b600d55565b606060048054610c9690612db9565b6116266123fe565b600a80549115156101000261ff0019909216919091179055565b60006001600160a01b038216611669576040516322646a9760e21b815260040160405180910390fd5b506001600160a01b031660009081526006602052604090205460ff16151560011490565b6116956123fe565b806116b3576040516363868c5560e11b815260040160405180910390fd5b6040516370a0823160e01b8152306004820152829082906001600160a01b038316906370a082319060240160206040518083038186803b1580156116f657600080fd5b505afa15801561170a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172e9190612e41565b101561174d57604051631642df1760e21b815260040160405180910390fd5b60135460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018490529082169063a9059cbb90604401602060405180830381600087803b15801561179b57600080fd5b505af11580156117af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d39190612e5a565b50505050565b600033816117e78286611f30565b90508381101561180a57604051631642df1760e21b815260040160405180910390fd5b6110f182868684036120de565b3373a9dac8f3aedc55d0fe707b86b8a45d246858d2e11461184b57604051639b96b05160e01b815260040160405180910390fd5b600e55565b600033610d748185856122e6565b6118666123fe565b6001600160a01b03811661188d576040516322646a9760e21b815260040160405180910390fd5b6013546001600160a01b03828116911614156118bc5760405163a28a88c160e01b815260040160405180910390fd5b601380546001600160a01b0319166001600160a01b0392909216919091179055565b60165460ff1615611902576040516309c7220160e31b815260040160405180910390fd5b670de0b6b3a764000083101561192b5760405163b562e8dd60e01b815260040160405180910390fd5b61193361136f565b611950576040516309c7220160e31b815260040160405180910390fd5b61195b848383611179565b6119785760405163097b24df60e41b815260040160405180910390fd5b611981836114c4565b61199e576040516393eeb41560e01b815260040160405180910390fd5b6119a88484610d19565b6119c5576040516366be767160e11b815260040160405180910390fd5b6119ce83611aa6565b6119eb5760405163a4875a4960e01b815260040160405180910390fd5b6119f483612028565b3414611a135760405163078d696560e31b815260040160405180910390fd5b611a1b61218d565b611a2584846121cf565b6117d384846121f1565b611a376123fe565b670de0b6b3a7640000811015611a605760405163b562e8dd60e01b815260040160405180910390fd5b60005b8251811015611aa157611a8f838281518110611a8157611a81612e77565b6020026020010151836121f1565b80611a9981612e8d565b915050611a63565b505050565b60075460009060ff16611abb57506001919050565b611ac36115e7565b82611acd60025490565b611ad79190612e0a565b111592915050565b611ae76123fe565b600254811015611b0a5760405163cc67044560e01b815260040160405180910390fd5b600855565b611b176123fe565b6016805460ff19169055565b611b2b6123fe565b6007805460ff1916911515919091179055565b611b466123fe565b600a805460ff1916911515919091179055565b670de0b6b3a7640000821015611b825760405163b562e8dd60e01b815260040160405180910390fd5b611b8b82611aa6565b611ba85760405163a4875a4960e01b815260040160405180910390fd5b611bb0611580565b611bcd576040516306717a3b60e51b815260040160405180910390fd5b611bd6826114c4565b611bf3576040516393eeb41560e01b815260040160405180910390fd5b611bfd8383610d19565b611c1a576040516366be767160e11b815260040160405180910390fd5b600e543414611c3c5760405163078d696560e31b815260040160405180910390fd5b611c4581611242565b611c6257604051636c501c9960e11b815260040160405180910390fd5b600082611c6e83611eb2565b611c789190612e22565b6040516370a0823160e01b81526001600160a01b03868116600483015291925083918391908316906370a082319060240160206040518083038186803b158015611cc157600080fd5b505afa158015611cd5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf99190612e41565b1015611d1857604051631642df1760e21b815260040160405180910390fd5b604051636eb1769f60e11b81526001600160a01b03868116600483015230602483015283919083169063dd62ed3e9060440160206040518083038186803b158015611d6257600080fd5b505afa158015611d76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9a9190612e41565b1015611db95760405163017e286b60e51b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b03868116600483015230602483015260448201849052600091908316906323b872dd90606401602060405180830381600087803b158015611e0d57600080fd5b505af1158015611e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e459190612e5a565b905080611e6557604051633c9fd93960e21b815260040160405180910390fd5b611e6d61218d565b611e7786866121cf565b611e8186866121f1565b505050505050565b611e916123fe565b6001600160a01b03166000908152601160205260409020805460ff19169055565b6000611ebd82611242565b611eda57604051636c501c9960e11b815260040160405180910390fd5b506001600160a01b031660009081526011602052604090206001015490565b611f016123fe565b6001600160a01b03929092166000908152601160205260409020805460ff191691151591909117815560010155565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b611f6361257a565b6001600160a01b038116611f8a576040516322646a9760e21b815260040160405180910390fd5b611f9381611640565b611fb057604051638afaeb9d60e01b815260040160405180910390fd5b6001600160a01b03166000908152600660205260409020805460ff19169055565b611fd96123fe565b670de0b6b3a76400008110156120025760405163b562e8dd60e01b815260040160405180910390fd5b61200b81611aa6565b6114b65760405163a4875a4960e01b815260040160405180910390fd5b6000670de0b6b3a764000082101561205357604051631cdaa1ed60e31b815260040160405180910390fd5b6000612067670de0b6b3a764000084612ea8565b9050600e5481600d5461207a9190612e22565b6120849190612e0a565b9392505050565b61209361257a565b6001600160a01b0381166120ba576040516322646a9760e21b815260040160405180910390fd5b61127c816125d4565b6120cb6123fe565b6016805462ffff00191662010000179055565b6001600160a01b038316612105576040516322646a9760e21b815260040160405180910390fd5b6001600160a01b03821661212c576040516322646a9760e21b815260040160405180910390fd5b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600e5460405173a9dac8f3aedc55d0fe707b86b8a45d246858d2e19180156108fc02916000818181858888f1935050505015801561127c573d6000803e3d6000fd5b6001600160a01b03909116600090815260096020526040902080549091019055565b6001600160a01b038216612218576040516322646a9760e21b815260040160405180910390fd5b806002600082825461222a9190612e0a565b90915550506001600160a01b03821660009081526020819052604081208054839290612257908490612e0a565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b60006122ad8484611f30565b905060001981146117d357818110156122d957604051631642df1760e21b815260040160405180910390fd5b6117d384848484036120de565b6001600160a01b03831661230d576040516322646a9760e21b815260040160405180910390fd5b6001600160a01b038216612334576040516322646a9760e21b815260040160405180910390fd5b6001600160a01b0383166000908152602081905260409020548181101561236e57604051631642df1760e21b815260040160405180910390fd5b6001600160a01b038085166000908152602081905260408082208585039055918516815290812080548492906123a5908490612e0a565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516123f191815260200190565b60405180910390a36117d3565b6005546001600160a01b0316339081149060009061241b90611640565b905081806124265750805b6114c05760405162461bcd60e51b815260206004820152602960248201527f5465616d3a2063616c6c6572206973206e6f7420746865206f776e6572206f726044820152681034b7102a32b0b69760b91b60648201526084015b60405180910390fd5b60008261249685846126b3565b14949350505050565b6001600160a01b0382166124c6576040516322646a9760e21b815260040160405180910390fd5b6001600160a01b0382166000908152602081905260409020548181101561250057604051631642df1760e21b815260040160405180910390fd5b6001600160a01b038316600090815260208190526040812083830390556002805484929061252f908490612eca565b90915550506040518281526000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b6005546001600160a01b0316331461150d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612480565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b6015548110156114c0576126a16012828154811061264957612649612e77565b9060005260206000200160009054906101000a90046001600160a01b031660646014848154811061267c5761267c612e77565b9060005260206000200154856126929190612e22565b61269c9190612ea8565b612727565b806126ab81612e8d565b915050612629565b600081815b845181101561271f5760008582815181106126d5576126d5612e77565b602002602001015190508083116126fb576000838152602082905260409020925061270c565b600081815260208490526040902092505b508061271781612e8d565b9150506126b8565b509392505050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114612774576040519150601f19603f3d011682016040523d82523d6000602084013e612779565b606091505b5050905080611aa15760405162461bcd60e51b815260206004820152601060248201526f2a3930b739b332b9103330b4b632b21760811b6044820152606401612480565b508054600082559060005260206000209081019061127c919061287b565b828054828255906000526020600020908101928215612830579160200282015b8281111561283057825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906127fb565b5061283c92915061287b565b5090565b828054828255906000526020600020908101928215612830579160200282015b82811115612830578251825591602001919060010190612860565b5b8082111561283c576000815560010161287c565b600060208083528351808285015260005b818110156128bd578581018301518582016040015282016128a1565b818111156128cf576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b03811681146128fc57600080fd5b919050565b6000806040838503121561291457600080fd5b61291d836128e5565b946020939093013593505050565b60008083601f84011261293d57600080fd5b50813567ffffffffffffffff81111561295557600080fd5b6020830191508360208260051b850101111561297057600080fd5b9250929050565b60008060008060006080868803121561298f57600080fd5b612998866128e5565b945060208601359350604086013567ffffffffffffffff8111156129bb57600080fd5b6129c78882890161292b565b90945092506129da9050606087016128e5565b90509295509295909350565b6000806000606084860312156129fb57600080fd5b612a04846128e5565b9250612a12602085016128e5565b9150604084013590509250925092565b600060208284031215612a3457600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7a57612a7a612a3b565b604052919050565b600067ffffffffffffffff821115612a9c57612a9c612a3b565b5060051b60200190565b600082601f830112612ab757600080fd5b81356020612acc612ac783612a82565b612a51565b82815260059290921b84018101918181019086841115612aeb57600080fd5b8286015b84811015612b0d57612b00816128e5565b8352918301918301612aef565b509695505050505050565b60008060408385031215612b2b57600080fd5b823567ffffffffffffffff80821115612b4357600080fd5b612b4f86838701612aa6565b9350602091508185013581811115612b6657600080fd5b85019050601f81018613612b7957600080fd5b8035612b87612ac782612a82565b81815260059190911b82018301908381019088831115612ba657600080fd5b928401925b82841015612bc457833582529284019290840190612bab565b80955050505050509250929050565b600080600060408486031215612be857600080fd5b612bf1846128e5565b9250602084013567ffffffffffffffff811115612c0d57600080fd5b612c198682870161292b565b9497909650939450505050565b600060208284031215612c3857600080fd5b612084826128e5565b801515811461127c57600080fd5b600060208284031215612c6157600080fd5b813561208481612c41565b60008060008060608587031215612c8257600080fd5b612c8b856128e5565b935060208501359250604085013567ffffffffffffffff811115612cae57600080fd5b612cba8782880161292b565b95989497509550505050565b60008060408385031215612cd957600080fd5b823567ffffffffffffffff811115612cf057600080fd5b612cfc85828601612aa6565b95602094909401359450505050565b600080600060608486031215612d2057600080fd5b612d29846128e5565b925060208401359150612d3e604085016128e5565b90509250925092565b600080600060608486031215612d5c57600080fd5b612d65846128e5565b92506020840135612d7581612c41565b929592945050506040919091013590565b60008060408385031215612d9957600080fd5b612da2836128e5565b9150612db0602084016128e5565b90509250929050565b600181811c90821680612dcd57607f821691505b60208210811415612dee57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115612e1d57612e1d612df4565b500190565b6000816000190483118215151615612e3c57612e3c612df4565b500290565b600060208284031215612e5357600080fd5b5051919050565b600060208284031215612e6c57600080fd5b815161208481612c41565b634e487b7160e01b600052603260045260246000fd5b6000600019821415612ea157612ea1612df4565b5060010190565b600082612ec557634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612edc57612edc612df4565b50039056fea26469706673582212209af33394c65b1c033c9856392d32857f08225a976a16f5f311f0a5ea6cb4736864736f6c63430008090033
Verified Source Code Partial Match
Compiler: v0.8.9+commit.e5eed63a
EVM: london
Optimization: Yes (200 runs)
ERC20Plus.sol 1300 lines
// SPDX-License-Identifier: MIT
error TransactionCapExceeded();
error ExcessiveOwnedMints();
error MintZeroQuantity();
error InvalidPayment();
error CapExceeded();
error ValueCannotBeZero();
error CannotBeNullAddress();
error InvalidTeamChange();
error InvalidInputValue();
error NoStateChange();
error PublicMintingClosed();
error AllowlistMintClosed();
error AddressNotAllowlisted();
error OnlyERC20MintingEnabled();
error ERC20TokenNotApproved();
error ERC20InsufficientBalance();
error ERC20InsufficientAllowance();
error ERC20TransferFailed();
error ERC20CappedInvalidValue();
error NotMaintainer();
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.
*
*
* 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 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++) {
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)
}
}
}
// 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/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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);
}
// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
if(currentAllowance < subtractedValue) revert ERC20InsufficientBalance();
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
if(from == address(0)) revert CannotBeNullAddress();
if(to == address(0)) revert CannotBeNullAddress();
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
if(fromBalance < amount) revert ERC20InsufficientBalance();
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
if(account == address(0)) revert CannotBeNullAddress();
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
if(account == address(0)) revert CannotBeNullAddress();
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
if(accountBalance < amount) revert ERC20InsufficientBalance();
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
if(owner == address(0)) revert CannotBeNullAddress();
if(spender == address(0)) revert CannotBeNullAddress();
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
if(currentAllowance < amount) revert ERC20InsufficientBalance();
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
// File: contracts/erc20.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)
pragma solidity ^0.8.0;
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}
}
// 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 {
if(newOwner == address(0)) revert CannotBeNullAddress();
_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);
}
}
// Rampp Contracts v2.1 (Teams.sol)
pragma solidity ^0.8.0;
/**
* Teams is a contract implementation to extend upon Ownable that allows multiple controllers
* of a single contract to modify specific mint settings but not have overall ownership of the contract.
* This will easily allow cross-collaboration via Mintplex.xyz.
**/
abstract contract Teams is Ownable{
mapping (address => bool) internal team;
/**
* @dev Adds an address to the team. Allows them to execute protected functions
* @param _address the ETH address to add, cannot be 0x and cannot be in team already
**/
function addToTeam(address _address) public onlyOwner {
if(_address == address(0)) revert CannotBeNullAddress();
if(inTeam(_address)) revert InvalidTeamChange();
team[_address] = true;
}
/**
* @dev Removes an address to the team.
* @param _address the ETH address to remove, cannot be 0x and must be in team
**/
function removeFromTeam(address _address) public onlyOwner {
if(_address == address(0)) revert CannotBeNullAddress();
if(!inTeam(_address)) revert InvalidTeamChange();
team[_address] = false;
}
/**
* @dev Check if an address is valid and active in the team
* @param _address ETH address to check for truthiness
**/
function inTeam(address _address)
public
view
returns (bool)
{
if(_address == address(0)) revert CannotBeNullAddress();
return team[_address] == true;
}
/**
* @dev Throws if called by any account other than the owner or team member.
*/
function _onlyTeamOrOwner() private view {
bool _isOwner = owner() == _msgSender();
bool _isTeam = inTeam(_msgSender());
require(_isOwner || _isTeam, "Team: caller is not the owner or in Team.");
}
modifier onlyTeamOrOwner() {
_onlyTeamOrOwner();
_;
}
}
// @dev Allows the contract to have an enforceable supply cap.
// @notice This is toggleable by the team, so supply can be unlimited/limited at will.
abstract contract ERC20Capped is ERC20, Teams {
bool public _capEnabled;
uint256 internal _cap; // Supply Cap of entire token contract
function setCapStatus(bool _capStatus) public onlyTeamOrOwner {
_capEnabled = _capStatus;
}
function canMintAmount(uint256 _amount) public view returns (bool) {
if(!_capEnabled){ return true; }
return ERC20.totalSupply() + _amount <= supplyCap();
}
// @dev Update the total possible supply to a new value.
// @notice _newCap must be greater than or equal to the currently minted supply
// @param _newCap is the new amount of tokens available in wei
function setSupplyCap(uint256 _newCap) public onlyTeamOrOwner {
if(_newCap < ERC20.totalSupply()) revert ERC20CappedInvalidValue();
_cap = _newCap;
}
function supplyCap() public view virtual returns (uint256) {
if(!_capEnabled){ return ERC20.totalSupply(); }
return _cap;
}
}
abstract contract Feeable is Teams {
uint256 public PRICE = 0 ether;
uint256 public PROVIDER_FEE = 0.000777 ether;
address private constant PROVIDER = 0xa9dAC8f3aEDC55D0FE707B86B8A45d246858d2E1;
function setPrice(uint256 _feeInWei) public onlyTeamOrOwner {
PRICE = _feeInWei;
}
// @dev quickly calculate the fee that will be required for a given qty to mint
// @notice _count is the value in wei, not in human readable count
// @param _count is representation of quantity in wei. it will be converted to eth to arrive at proper value
function getPrice(uint256 _count) public view returns (uint256) {
if(_count < 1 ether) revert InvalidInputValue();
uint256 countHuman = _count / 1 ether;
return (PRICE * countHuman) + PROVIDER_FEE;
}
function sendProviderFee() internal {
payable(PROVIDER).transfer(PROVIDER_FEE);
}
function setProviderFee(uint256 _fee) public {
if(_msgSender() != PROVIDER) revert NotMaintainer();
PROVIDER_FEE = _fee;
}
}
// File: Allowlist.sol
pragma solidity ^0.8.0;
abstract contract Allowlist is Teams {
bytes32 public merkleRoot;
bool public onlyAllowlistMode = false;
/**
* @dev Update merkle root to reflect changes in Allowlist
* @param _newMerkleRoot new merkle root to reflect most recent Allowlist
*/
function updateMerkleRoot(bytes32 _newMerkleRoot) public onlyTeamOrOwner {
if(_newMerkleRoot == merkleRoot) revert NoStateChange();
merkleRoot = _newMerkleRoot;
}
/**
* @dev Check the proof of an address if valid for merkle root
* @param _to address to check for proof
* @param _merkleProof Proof of the address to validate against root and leaf
*/
function isAllowlisted(address _to, bytes32[] calldata _merkleProof) public view returns(bool) {
if(merkleRoot == 0) revert ValueCannotBeZero();
bytes32 leaf = keccak256(abi.encodePacked(_to));
return MerkleProof.verify(_merkleProof, merkleRoot, leaf);
}
function enableAllowlistOnlyMode() public onlyTeamOrOwner {
onlyAllowlistMode = true;
}
function disableAllowlistOnlyMode() public onlyTeamOrOwner {
onlyAllowlistMode = false;
}
}
// File: WithdrawableV2
// This abstract allows the contract to be able to mint and ingest ERC-20 payments for mints.
// ERC-20 Payouts are limited to a single payout address.
abstract contract WithdrawableV2 is Teams {
struct acceptedERC20 {
bool isActive;
uint256 chargeAmount;
}
mapping(address => acceptedERC20) private allowedTokenContracts;
address[] public payableAddresses;
address public erc20Payable;
uint256[] public payableFees;
uint256 public payableAddressCount;
bool public onlyERC20MintingMode;
function withdrawAll() public onlyTeamOrOwner {
if(address(this).balance == 0) revert ValueCannotBeZero();
_withdrawAll(address(this).balance);
}
function _withdrawAll(uint256 balance) private {
for(uint i=0; i < payableAddressCount; i++ ) {
_widthdraw(
payableAddresses[i],
(balance * payableFees[i]) / 100
);
}
}
function _widthdraw(address _address, uint256 _amount) private {
(bool success, ) = _address.call{value: _amount}("");
require(success, "Transfer failed.");
}
/**
* @dev Allow contract owner to withdraw ERC-20 balance from contract
* in the event ERC-20 tokens are paid to the contract for mints.
* @param _tokenContract contract of ERC-20 token to withdraw
* @param _amountToWithdraw balance to withdraw according to balanceOf of ERC-20 token in wei
*/
function withdrawERC20(address _tokenContract, uint256 _amountToWithdraw) public onlyTeamOrOwner {
if(_amountToWithdraw == 0) revert ValueCannotBeZero();
IERC20 tokenContract = IERC20(_tokenContract);
if(tokenContract.balanceOf(address(this)) < _amountToWithdraw) revert ERC20InsufficientBalance();
tokenContract.transfer(erc20Payable, _amountToWithdraw); // Payout ERC-20 tokens to recipient
}
/**
* @dev check if an ERC-20 contract is a valid payable contract for executing a mint.
* @param _erc20TokenContract address of ERC-20 contract in question
*/
function isApprovedForERC20Payments(address _erc20TokenContract) public view returns(bool) {
return allowedTokenContracts[_erc20TokenContract].isActive == true;
}
/**
* @dev get the value of tokens to transfer for user of an ERC-20
* @param _erc20TokenContract address of ERC-20 contract in question
*/
function chargeAmountForERC20(address _erc20TokenContract) public view returns(uint256) {
if(!isApprovedForERC20Payments(_erc20TokenContract)) revert ERC20TokenNotApproved();
return allowedTokenContracts[_erc20TokenContract].chargeAmount;
}
/**
* @dev Explicity sets and ERC-20 contract as an allowed payment method for minting
* @param _erc20TokenContract address of ERC-20 contract in question
* @param _isActive default status of if contract should be allowed to accept payments
* @param _chargeAmountInTokens fee (in tokens) to charge for mints for this specific ERC-20 token
*/
function addOrUpdateERC20ContractAsPayment(address _erc20TokenContract, bool _isActive, uint256 _chargeAmountInTokens) public onlyTeamOrOwner {
allowedTokenContracts[_erc20TokenContract].isActive = _isActive;
allowedTokenContracts[_erc20TokenContract].chargeAmount = _chargeAmountInTokens;
}
/**
* @dev Add an ERC-20 contract as being a valid payment method. If passed a contract which has not been added
* it will assume the default value of zero. This should not be used to create new payment tokens.
* @param _erc20TokenContract address of ERC-20 contract in question
*/
function enableERC20ContractAsPayment(address _erc20TokenContract) public onlyTeamOrOwner {
allowedTokenContracts[_erc20TokenContract].isActive = true;
}
/**
* @dev Disable an ERC-20 contract as being a valid payment method. If passed a contract which has not been added
* it will assume the default value of zero. This should not be used to create new payment tokens.
* @param _erc20TokenContract address of ERC-20 contract in question
*/
function disableERC20ContractAsPayment(address _erc20TokenContract) public onlyTeamOrOwner {
allowedTokenContracts[_erc20TokenContract].isActive = false;
}
/**
* @dev Enable only ERC-20 payments for minting on this contract
*/
function enableERC20OnlyMinting() public onlyTeamOrOwner {
onlyERC20MintingMode = true;
}
/**
* @dev Disable only ERC-20 payments for minting on this contract
*/
function disableERC20OnlyMinting() public onlyTeamOrOwner {
onlyERC20MintingMode = false;
}
/**
* @dev Set the payout of the ERC-20 token payout to a specific address
* @param _newErc20Payable new payout addresses of ERC-20 tokens
*/
function setERC20PayableAddress(address _newErc20Payable) public onlyTeamOrOwner {
if(_newErc20Payable == address(0)) revert CannotBeNullAddress();
if(_newErc20Payable == erc20Payable) revert NoStateChange();
erc20Payable = _newErc20Payable;
}
function definePayables(address[] memory _newPayables, uint256[] memory _newFees) public onlyTeamOrOwner {
delete payableAddresses;
delete payableFees;
payableAddresses = _newPayables;
payableFees = _newFees;
payableAddressCount = _newPayables.length;
}
}
// @dev Allows us to add per wallet and per transaction caps to the minting aspect of this ERC20
abstract contract ERC20MintCaps is Teams {
mapping(address => uint256) private _minted;
bool internal _mintCapEnabled; // per wallet mint cap
bool internal _batchSizeEnabled; // txn batch size limit
uint256 internal mintCap; // in wei
uint256 internal maxBatchSize; // in wei
function setMintCap(uint256 _newMintCap) public onlyTeamOrOwner {
mintCap = _newMintCap;
}
function setMintCapStatus(bool _newStatus) public onlyTeamOrOwner {
_mintCapEnabled = _newStatus;
}
function setMaxBatchSize(uint256 _maxBatchSize) public onlyTeamOrOwner {
maxBatchSize = _maxBatchSize;
}
function setMaxBatchSizeStatus(bool _newStatus) public onlyTeamOrOwner {
_batchSizeEnabled = _newStatus;
}
// @dev Check if amount of tokens is possible to be minted
// @param _amount is the amount of tokens in wei
function canMintBatch(uint256 _amount) public view returns (bool) {
if(!_batchSizeEnabled){ return true; }
return _amount <= maxBatchSize;
}
// @dev returns if current mint caps are enabled (mints per wallet)
// @return bool if mint caps per wallet are enforced
function mintCapEnabled() public view returns (bool) {
return _mintCapEnabled;
}
// @dev the current mintCap in decimals value
// @return uint256 of mint caps per wallet. mintCapEnabled can be disabled and this value be non-zero.
function maxWalletMints() public view returns(uint256) {
return mintCap;
}
// @dev returns if current batch size caps are enabled (mints per txn)
// @return bool if mint caps per transaction are enforced
function mintBatchSizeEnabled() public view returns (bool) {
return _batchSizeEnabled;
}
// @dev the current cap for a single txn in decimals value
// @return uint256 the current cap for a single txn in decimals value
function maxMintsPerTxn() public view returns (uint256) {
return maxBatchSize;
}
// @dev checks if the mint count of an account is within the proper range
// @notice if maxWalletMints is false it will always return true
// @param _account is address to check
// @param _amount is the amount of tokens in wei to be added to current minted supply
function canAccountMintAmount(address _account, uint256 _amount) public view returns (bool) {
if(!_mintCapEnabled){ return true; }
return mintedAmount(_account) + _amount <= mintCap;
}
// @dev gets currently minted amount for an account
// @return uint256 of tokens owned in base decimal value (wei)
function mintedAmount(address _account) public view returns (uint256) {
return _minted[_account];
}
// @dev helper function that increased the mint amount for an account
// @notice this is not the same as _balances, as that can vary as trades occur.
// @param _account is address to add to
// @param _amount is the amount of tokens in wei to be added to current minted amount
function addMintsToAccount(address _account, uint256 _amount) internal {
unchecked {
_minted[_account] += _amount;
}
}
}
abstract contract SingleStateMintable is Teams {
bool internal publicMintOpen = false;
bool internal allowlistMintOpen = false;
function inPublicMint() public view returns (bool){
return publicMintOpen && !allowlistMintOpen;
}
function inAllowlistMint() public view returns (bool){
return allowlistMintOpen && !publicMintOpen;
}
function openPublicMint() public onlyTeamOrOwner {
publicMintOpen = true;
allowlistMintOpen = false;
}
function openAllowlistMint() public onlyTeamOrOwner {
allowlistMintOpen = true;
publicMintOpen = false;
}
// @notice This will set close all minting to public regardless of previous state
function closeMinting() public onlyTeamOrOwner {
allowlistMintOpen = false;
publicMintOpen = false;
}
}
// File: contracts/ERC20Plus.sol
pragma solidity ^0.8.0;
contract ERC20Plus is
Ownable,
ERC20Burnable,
ERC20Capped,
ERC20MintCaps,
Feeable,
Allowlist,
WithdrawableV2,
SingleStateMintable
{
uint8 immutable CONTRACT_VERSION = 1;
constructor(
string memory name,
string memory symbol,
address[] memory _payableAddresses,
address _erc20Payable,
uint256[] memory _payableFees,
bool[3] memory mintSettings, // hasMaxSupply, mintCapEnabled, maxBatchEnabled
uint256[3] memory mintValues, // initMaxSupply, initMintCap, initBatchSize
uint256 initPrice
) ERC20(name, symbol) {
// Payable settings
payableAddresses = _payableAddresses;
erc20Payable = _erc20Payable;
payableFees = _payableFees;
payableAddressCount = _payableAddresses.length;
// Set inital Supply cap settings
_capEnabled = mintSettings[0];
_cap = mintValues[0];
// Per wallet minting settings
_mintCapEnabled = mintSettings[1];
mintCap = mintValues[1];
// Per txn minting settings
_batchSizeEnabled = mintSettings[2];
maxBatchSize = mintValues[2];
// setup price
PRICE = initPrice;
}
/////////////// Admin Mint Functions
/**
* @dev Mints tokens to an address.
* This is owner only and allows a fee-free drop
* @param _to address of the future owner of the token
* @param _qty amount of tokens to drop the owner in decimal value (wei typically 1e18)
*/
function adminMint(address _to, uint256 _qty) public onlyTeamOrOwner{
if(_qty < 1 ether) revert MintZeroQuantity();
if(!canMintAmount(_qty)) revert CapExceeded();
_mint(_to, _qty);
}
function adminMintBulk(address[] memory _tos, uint256 _qty) public onlyTeamOrOwner{
if(_qty < 1 ether) revert MintZeroQuantity();
for(uint i=0; i < _tos.length; i++ ) {
_mint(_tos[i], _qty);
}
}
/////////////// GENERIC MINT FUNCTIONS
/**
* @dev Mints tokens to an address in batch.
* fee may or may not be required*
* @param _to address of the future owner of the token
* @param _amount number of tokens to mint in wei
*/
function mintMany(address _to, uint256 _amount) public payable {
if(onlyERC20MintingMode) revert PublicMintingClosed();
if(_amount < 1 ether) revert MintZeroQuantity();
if(!inPublicMint()) revert PublicMintingClosed();
if(!canMintBatch(_amount)) revert TransactionCapExceeded();
if(!canMintAmount(_amount)) revert CapExceeded();
if(!canAccountMintAmount(_to, _amount)) revert ExcessiveOwnedMints();
if(msg.value != getPrice(_amount)) revert InvalidPayment();
sendProviderFee();
addMintsToAccount(_to, _amount);
_mint(_to, _amount);
}
/**
* @dev Mints tokens to an address in batch using an ERC-20 token for payment
* fee may or may not be required*
* @param _to address of the future owner of the token
* @param _amount number of tokens to mint in wei
* @param _erc20TokenContract erc-20 token contract to mint with
*/
function mintManyERC20(address _to, uint256 _amount, address _erc20TokenContract) public payable {
if(_amount < 1 ether) revert MintZeroQuantity();
if(!canMintAmount(_amount)) revert CapExceeded();
if(!inPublicMint()) revert PublicMintingClosed();
if(!canMintBatch(_amount)) revert TransactionCapExceeded();
if(!canAccountMintAmount(_to, _amount)) revert ExcessiveOwnedMints();
if(msg.value != PROVIDER_FEE) revert InvalidPayment();
// ERC-20 Specific pre-flight checks
if(!isApprovedForERC20Payments(_erc20TokenContract)) revert ERC20TokenNotApproved();
uint256 tokensQtyToTransfer = chargeAmountForERC20(_erc20TokenContract) * _amount;
IERC20 payableToken = IERC20(_erc20TokenContract);
if(payableToken.balanceOf(_to) < tokensQtyToTransfer) revert ERC20InsufficientBalance();
if(payableToken.allowance(_to, address(this)) < tokensQtyToTransfer) revert ERC20InsufficientAllowance();
bool transferComplete = payableToken.transferFrom(_to, address(this), tokensQtyToTransfer);
if(!transferComplete) revert ERC20TransferFailed();
sendProviderFee();
addMintsToAccount(_to, _amount);
_mint(_to, _amount);
}
/**
* @dev Mints tokens to an address using an allowlist.
* fee may or may not be required*
* @param _to address of the future owner of the token
* @param _amount number of tokens to mint in wei
* @param _merkleProof merkle proof array
*/
function mintManyAL(address _to, uint256 _amount, bytes32[] calldata _merkleProof) public payable {
if(onlyERC20MintingMode) revert AllowlistMintClosed();
if(_amount < 1 ether) revert MintZeroQuantity();
if(!inAllowlistMint()) revert AllowlistMintClosed();
if(!isAllowlisted(_to, _merkleProof)) revert AddressNotAllowlisted();
if(!canMintBatch(_amount)) revert TransactionCapExceeded();
if(!canAccountMintAmount(_to, _amount)) revert ExcessiveOwnedMints();
if(!canMintAmount(_amount)) revert CapExceeded();
if(msg.value != getPrice(_amount)) revert InvalidPayment();
sendProviderFee();
addMintsToAccount(_to, _amount);
_mint(_to, _amount);
}
/**
* @dev Mints tokens to an address using an allowlist.
* fee may or may not be required*
* @param _to address of the future owner of the token
* @param _amount number of tokens to mint in wei
* @param _merkleProof merkle proof array
* @param _erc20TokenContract erc-20 token contract to mint with
*/
function mintManyERC20AL(address _to, uint256 _amount, bytes32[] calldata _merkleProof, address _erc20TokenContract) public payable {
if(!inAllowlistMint()) revert AllowlistMintClosed();
if(_amount < 1 ether) revert MintZeroQuantity();
if(!isAllowlisted(_to, _merkleProof)) revert AddressNotAllowlisted();
if(!canMintBatch(_amount)) revert TransactionCapExceeded();
if(!canAccountMintAmount(_to, _amount)) revert ExcessiveOwnedMints();
if(!canMintAmount(_amount)) revert CapExceeded();
if(msg.value != PROVIDER_FEE) revert InvalidPayment();
// ERC-20 Specific pre-flight checks
if(!isApprovedForERC20Payments(_erc20TokenContract)) revert ERC20TokenNotApproved();
uint256 tokensQtyToTransfer = chargeAmountForERC20(_erc20TokenContract) * _amount;
IERC20 payableToken = IERC20(_erc20TokenContract);
if(payableToken.balanceOf(_to) < tokensQtyToTransfer) revert ERC20InsufficientBalance();
if(payableToken.allowance(_to, address(this)) < tokensQtyToTransfer) revert ERC20InsufficientAllowance();
bool transferComplete = payableToken.transferFrom(_to, address(this), tokensQtyToTransfer);
if(!transferComplete) revert ERC20TransferFailed();
sendProviderFee();
addMintsToAccount(_to, _amount);
_mint(_to, _amount);
}
}
Read Contract
PRICE 0x8d859f3e → uint256
PROVIDER_FEE 0xf623bb8b → uint256
_capEnabled 0x20fab142 → bool
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
canAccountMintAmount 0x0825850a → bool
canMintAmount 0xb0cfbf16 → bool
canMintBatch 0x627255df → bool
chargeAmountForERC20 0xd266f3a9 → uint256
decimals 0x313ce567 → uint8
erc20Payable 0x7fb8c6d3 → address
getPrice 0xe7572230 → uint256
inAllowlistMint 0x4c23ce91 → bool
inPublicMint 0x88993c81 → bool
inTeam 0xa1af10ca → bool
isAllowlisted 0x33006786 → bool
isApprovedForERC20Payments 0x3d3f9c57 → bool
maxMintsPerTxn 0xaf54001e → uint256
maxWalletMints 0x34d00766 → uint256
merkleRoot 0x2eb4a7ab → bytes32
mintBatchSizeEnabled 0xf82fa756 → bool
mintCapEnabled 0x1963d0cc → bool
mintedAmount 0xfbbf8cc3 → uint256
name 0x06fdde03 → string
onlyAllowlistMode 0xe6c6990a → bool
onlyERC20MintingMode 0x46f41ed5 → bool
owner 0x8da5cb5b → address
payableAddressCount 0x3e07311c → uint256
payableAddresses 0x891bbe73 → address
payableFees 0x286c8137 → uint256
supplyCap 0x8f770ad0 → uint256
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
Write Contract 40 functions
These functions modify contract state and require a wallet transaction to execute.
addOrUpdateERC20ContractAsPayment 0xd83ae332
address _erc20TokenContract
bool _isActive
uint256 _chargeAmountInTokens
addToTeam 0x43696f18
address _address
adminMint 0xe58306f9
address _to
uint256 _qty
adminMintBulk 0xafb16d18
address[] _tos
uint256 _qty
approve 0x095ea7b3
address spender
uint256 amount
returns: bool
burn 0x42966c68
uint256 amount
burnFrom 0x79cc6790
address account
uint256 amount
closeMinting 0x87491c60
No parameters
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
definePayables 0x28ff1b51
address[] _newPayables
uint256[] _newFees
disableAllowlistOnlyMode 0x6d3de806
No parameters
disableERC20ContractAsPayment 0xcacf0842
address _erc20TokenContract
disableERC20OnlyMinting 0xb94b2376
No parameters
enableAllowlistOnlyMode 0x79ab3c89
No parameters
enableERC20ContractAsPayment 0x464c3428
address _erc20TokenContract
enableERC20OnlyMinting 0x89f26d58
No parameters
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
mintMany 0x5e830656
address _to
uint256 _amount
mintManyAL 0xad1203dc
address _to
uint256 _amount
bytes32[] _merkleProof
mintManyERC20 0xc6ee6e35
address _to
uint256 _amount
address _erc20TokenContract
mintManyERC20AL 0x2181384e
address _to
uint256 _amount
bytes32[] _merkleProof
address _erc20TokenContract
openAllowlistMint 0xf8c0fd20
No parameters
openPublicMint 0x45f7e06e
No parameters
removeFromTeam 0xdfdedf69
address _address
renounceOwnership 0x715018a6
No parameters
setCapStatus 0xc3268768
bool _capStatus
setERC20PayableAddress 0xa91bd1a9
address _newErc20Payable
setMaxBatchSize 0x2b26a6bf
uint256 _maxBatchSize
setMaxBatchSizeStatus 0x98ad4417
bool _newStatus
setMintCap 0x4070a0c9
uint256 _newMintCap
setMintCapStatus 0xc3cb97c6
bool _newStatus
setPrice 0x91b7f5ed
uint256 _feeInWei
setProviderFee 0xa7593fb7
uint256 _fee
setSupplyCap 0xb6a3f59a
uint256 _newCap
transfer 0xa9059cbb
address to
uint256 amount
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 amount
returns: bool
transferOwnership 0xf2fde38b
address newOwner
updateMerkleRoot 0x4783f0ef
bytes32 _newMerkleRoot
withdrawAll 0x853828b6
No parameters
withdrawERC20 0xa1db9782
address _tokenContract
uint256 _amountToWithdraw
Recent Transactions
No transactions found for this address