Address Contract Verified
Address
0xA9249959cd6AEFd91264416fF283885aF5e252A3
Balance
0 ETH
Nonce
1
Code Size
18871 bytes
Creator
0xCa9f1c2F...1403 at tx 0x34729694...3e5350
Indexed Transactions
0
Contract Bytecode
18871 bytes
0x6080604052600436106103f95760003560e01c80637f6fb2531161020d578063c8adff0111610128578063e6da9213116100bb578063edec5f271161008a578063f597573f1161006f578063f597573f14610b70578063f885838614610b90578063fe575a8714610bb057600080fd5b8063edec5f2714610b30578063f2fde38b14610b5057600080fd5b8063e6da921314610aba578063e985e36714610ada578063eac0d11514610afa578063eadd94ec14610b1a57600080fd5b8063cff805ab116100f7578063cff805ab14610a44578063d1690fec14610a5a578063e19648db14610a7a578063e32204dd14610a9a57600080fd5b8063c8adff01146109da578063cad00556146109ef578063cb1a4fc014610a0f578063cedcc6da14610a2457600080fd5b80639a89c1fb116101a0578063ba166a391161016f578063ba166a391461094d578063bb3d676a1461097a578063c23326f31461099a578063c6ae7178146109ba57600080fd5b80639a89c1fb146108d75780639cfa0f7c146108f7578063a6d42e4e1461090d578063ae1042651461092d57600080fd5b80638da5cb5b116101dc5780638da5cb5b1461086e5780638e15f4731461088c578063920a253e146108a1578063995deaba146108b757600080fd5b80637f6fb2531461080e5780638456cb591461082457806389daf799146108395780638afbf6691461085957600080fd5b806343568eae1161031857806363b20117116102ab578063715018a61161027a578063741bef1a1161025f578063741bef1a146107b857806378e97925146107d85780637ad71f72146107ee57600080fd5b8063715018a61461077357806373b2e80e1461078857600080fd5b806363b201171461070857806363e408791461071e578063641046f41461073e5780636b4052fc1461075357600080fd5b8063548db174116102e7578063548db1741461069a5780635bc34f71146106ba5780635c975abb146106d05780635ddc5688146106e857600080fd5b806343568eae1461062e578063485cc955146106445780634e71d92d1461066457806353d992071461067957600080fd5b806329a5a0b611610390578063386466081161035f578063386466081461059e5780633af32abf146105d65780633f4ba83a146106065780634151848f1461061b57600080fd5b806329a5a0b6146105325780632dc358e8146105525780633197cbb61461057257806333f761781461058857600080fd5b80631fa2bc92116103cc5780631fa2bc92146104a0578063232e95be146104d157806323a8f1c0146104f2578063278c278b1461051257600080fd5b80630a200fc7146103fe5780630ba36dcd146104205780630dc9c838146104605780631ddc609114610480575b600080fd5b34801561040a57600080fd5b5061041e61041936600461432e565b610be0565b005b34801561042c57600080fd5b5061044d61043b366004614367565b60df6020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561046c57600080fd5b5061041e61047b366004614382565b610c21565b34801561048c57600080fd5b5061041e61049b36600461432e565b610e62565b3480156104ac57600080fd5b5060db546104c190600160a01b900460ff1681565b6040519015158152602001610457565b3480156104dd57600080fd5b5060db546104c190600160b01b900460ff1681565b3480156104fe57600080fd5b5061041e61050d3660046143a4565b610ea3565b34801561051e57600080fd5b5061041e61052d3660046143a4565b610eb0565b34801561053e57600080fd5b5061044d61054d3660046143a4565b610f53565b34801561055e57600080fd5b5061041e61056d3660046144bc565b610f87565b34801561057e57600080fd5b5061044d60cb5481565b34801561059457600080fd5b5061044d60cd5481565b3480156105aa57600080fd5b5060dd546105be906001600160a01b031681565b6040516001600160a01b039091168152602001610457565b3480156105e257600080fd5b506104c16105f1366004614367565b60e26020526000908152604090205460ff1681565b34801561061257600080fd5b5061041e61103d565b6104c16106293660046144f9565b61104f565b34801561063a57600080fd5b5061044d60d25481565b34801561065057600080fd5b5061041e61065f366004614537565b6116b6565b34801561067057600080fd5b506104c1611826565b34801561068557600080fd5b5060db546104c190600160a81b900460ff1681565b3480156106a657600080fd5b5061041e6106b536600461456a565b611bb8565b3480156106c657600080fd5b5061044d60cf5481565b3480156106dc57600080fd5b5060975460ff166104c1565b3480156106f457600080fd5b5061041e6107033660046145df565b611c32565b34801561071457600080fd5b5061044d60c95481565b34801561072a57600080fd5b5061044d6107393660046143a4565b611e5b565b34801561074a57600080fd5b5061041e611e7d565b34801561075f57600080fd5b5061041e61076e366004614367565b611fe2565b34801561077f57600080fd5b5061041e61206f565b34801561079457600080fd5b506104c16107a3366004614367565b60e06020526000908152604090205460ff1681565b3480156107c457600080fd5b5060de546105be906001600160a01b031681565b3480156107e457600080fd5b5061044d60ca5481565b3480156107fa57600080fd5b506105be6108093660046143a4565b612081565b34801561081a57600080fd5b5061044d60d35481565b34801561083057600080fd5b5061041e6120ab565b34801561084557600080fd5b5061041e61085436600461456a565b6120bb565b34801561086557600080fd5b5061041e612135565b34801561087a57600080fd5b506065546001600160a01b03166105be565b34801561089857600080fd5b5061044d6122fa565b3480156108ad57600080fd5b5061044d60e35481565b3480156108c357600080fd5b5060e4546105be906001600160a01b031681565b3480156108e357600080fd5b5061041e6108f2366004614382565b61238b565b34801561090357600080fd5b5061044d60ce5481565b34801561091957600080fd5b5061041e61092836600461469f565b61239e565b34801561093957600080fd5b5061044d6109483660046143a4565b6123b3565b34801561095957600080fd5b5061096d6109683660046143a4565b612714565b604051610457919061473a565b34801561098657600080fd5b5061041e61099536600461456a565b612780565b3480156109a657600080fd5b5061044d6109b53660046143a4565b6127fa565b3480156109c657600080fd5b506104c16109d536600461477e565b61281b565b3480156109e657600080fd5b5061096d612a9b565b3480156109fb57600080fd5b5061041e610a0a366004614367565b612af3565b348015610a1b57600080fd5b506104c1612b80565b348015610a3057600080fd5b5061041e610a3f3660046143a4565b612dfd565b348015610a5057600080fd5b5061044d60d05481565b348015610a6657600080fd5b506104c1610a753660046144f9565b612e5b565b348015610a8657600080fd5b5061044d610a953660046143a4565b613666565b348015610aa657600080fd5b5060db546105be906001600160a01b031681565b348015610ac657600080fd5b5061044d610ad5366004614382565b613676565b348015610ae657600080fd5b5060cc546105be906001600160a01b031681565b348015610b0657600080fd5b5061041e610b1536600461432e565b6136aa565b348015610b2657600080fd5b5061044d60d15481565b348015610b3c57600080fd5b5061041e610b4b36600461456a565b6136eb565b348015610b5c57600080fd5b5061041e610b6b366004614367565b613765565b348015610b7c57600080fd5b5060dc546105be906001600160a01b031681565b348015610b9c57600080fd5b5061044d610bab3660046143a4565b6137f5565b348015610bbc57600080fd5b506104c1610bcb366004614367565b60e16020526000908152604090205460ff1681565b610be8613805565b60db8054911515600160a01b027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b610c29613805565b6000821180610c385750600081115b610c895760405162461bcd60e51b815260206004820152601260248201527f496e76616c696420706172616d6574657273000000000000000000000000000060448201526064015b60405180910390fd5b8115610d9b5760ca544210610ce05760405162461bcd60e51b815260206004820152601460248201527f53616c6520616c726561647920737461727465640000000000000000000000006044820152606401610c80565b814210610d2f5760405162461bcd60e51b815260206004820152601160248201527f53616c652074696d6520696e20706173740000000000000000000000000000006044820152606401610c80565b60ca8054908390556040805182815260208101859052428183015290517f5354415254000000000000000000000000000000000000000000000000000000917fddd2ed237e6993c9380182683f2c8bec486aaaa429528852cd74dbdb96cea0b2919081900360600190a2505b8015610e5e5760ca548111610df25760405162461bcd60e51b815260206004820152600f60248201527f496e76616c696420656e6454696d6500000000000000000000000000000000006044820152606401610c80565b60cb8054908290556040805182815260208101849052428183015290517f454e440000000000000000000000000000000000000000000000000000000000917fddd2ed237e6993c9380182683f2c8bec486aaaa429528852cd74dbdb96cea0b2919081900360600190a2505b5050565b610e6a613805565b60db8054911515600160a81b027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff909216919091179055565b610eab613805565b60d255565b610eb8613805565b60008111610f085760405162461bcd60e51b815260206004820152601c60248201527f5a65726f206d617820746f6b656e7320746f206275792076616c7565000000006044820152606401610c80565b60ce8054908290556040805182815260208101849052428183015290517f76f9e5e1f6af6a9f180708b77a5c99210fbf19b91f1f194f3918c262b8edf77c9181900360600190a15050565b600080610f5f836123b3565b9050610f696122fa565b60cd54610f7690836147e4565b610f8091906147fb565b9392505050565b610f8f613805565b8051600003610fe05760405162461bcd60e51b815260206004820152601c60248201527f63616e6e6f742075706461746520696e76616c69642076616c756573000000006044820152606401610c80565b610fec60d86000614239565b60005b8151811015610e5e5760d882828151811061100c5761100c61481d565b602090810291909101810151825460018101845560009384529190922001558061103581614833565b915050610fef565b611045613805565b61104d61385f565b565b60008360ca544210158015611066575060cb544211155b6110b25760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642074696d6520666f7220627579696e670000000000000000006044820152606401610c80565b600081116111025760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642073616c6520616d6f756e74000000000000000000000000006044820152606401610c80565b61110a6138b1565b60026001540361115c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c80565b6002600155600061116c866123b3565b905060006111786122fa565b60cd5461118590846147e4565b61118f91906147fb565b9050803410156111e15760405162461bcd60e51b815260206004820152600c60248201527f4c657373207061796d656e7400000000000000000000000000000000000000006044820152606401610c80565b60006111ed823461484c565b90508760c96000828254611201919061485f565b909155505060d05415611226578760d06000828254611220919061485f565b90915550505b600060d05460c9541161123b5760d05461123f565b60c9545b905060d460000160cf54815481106112595761125961481d565b9060005260206000200154811180611293575060d460020160cf54815481106112845761128461481d565b90600052602060002001544210155b156113cd5760d460020160cf54815481106112b0576112b061481d565b906000526020600020015442106112f3578860d460000160cf54815481106112da576112da61481d565b90600052602060002001546112ef919061485f565b60d0555b60db54600160a01b900460ff161561130d5761130d613904565b600060d4810160cf54815481106113265761132661481d565b9060005260206000200154821161137557898260d460000160cf54815481106113515761135161481d565b9060005260206000200154611366919061484c565b611370919061484c565b611378565b60005b60d880546001818101835560009283527f5320ad99a619a90804cd2efe3a5cf0ac1ac5c41ad9ff2c61cf699efdad77109690910183905560cf805493945090929091906113c690849061485f565b9091555050505b87156115245760db54600160b01b900460ff16156114445733600090815260e2602052604090205460ff166114445760405162461bcd60e51b815260206004820152601e60248201527f55736572206e6f742077686974656c697374656420666f72207374616b6500006044820152606401610c80565b60dd546001600160a01b03166391c619663360cd54611463908d6147e4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b1580156114a957600080fd5b505af11580156114bd573d6000803e3d6000fd5b505050508860d360008282546114d3919061485f565b90915550506040805184815260208101869052428183015290516000918b9133917f6f225532a9c33b023b8e48247ad8df9d98f132ae17c769b97ff22d2b278fa73a919081900360600190a461159d565b60cd54611531908a6147e4565b33600090815260df60205260408120805490919061155090849061485f565b90915550506040805184815260208101869052428183015290516000918b9133917f4d8aead3491b7eba4b5c7a65fc17e493b9e63f9e433522fc5f6a85a168fc9d36919081900360600190a45b8360d160008282546115af919061485f565b90915550506001600160a01b038716158015906115d557506001600160a01b0387163314155b80156115eb575060e4546001600160a01b031615155b1561168b576000606460e3548561160291906147e4565b61160c91906147fb565b9050611618818561484c565b60e4546040516322752acd60e11b81526001600160a01b038b8116600483015260248201859052600060448301529296509116906344ea559a9083906064016000604051808303818588803b15801561167057600080fd5b505af1158015611684573d6000803e3d6000fd5b5050505050505b61169483613974565b81156116a4576116a43383613adb565b50506001808055979650505050505050565b600054610100900460ff16158080156116d65750600054600160ff909116105b806116f05750303b1580156116f0575060005460ff166001145b6117625760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c80565b6000805460ff191660011790558015611785576000805461ff0019166101001790555b61178d613bce565b60de80546001600160a01b0380861673ffffffffffffffffffffffffffffffffffffffff199283161790925560dc805492851692909116919091179055670de0b6b3a764000060cd55600f60e3558015611821576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006118306138b1565b60cc546001600160a01b03166118885760405162461bcd60e51b815260206004820152601460248201527f53616c6520746f6b656e206e6f742061646465640000000000000000000000006044820152606401610c80565b33600090815260e1602052604090205460ff16156118e85760405162461bcd60e51b815260206004820152601b60248201527f54686973204164647265737320697320426c61636b6c697374656400000000006044820152606401610c80565b60db54600160a81b900460ff16156119595733600090815260e2602052604090205460ff166119595760405162461bcd60e51b815260206004820152601e60248201527f55736572206e6f742077686974656c697374656420666f7220636c61696d00006044820152606401610c80565b60cb544210156119ab5760405162461bcd60e51b815260206004820152601960248201527f436c61696d20686173206e6f74207374617274656420796574000000000000006044820152606401610c80565b33600090815260e0602052604090205460ff1615611a0b5760405162461bcd60e51b815260206004820152600f60248201527f416c726561647920636c61696d656400000000000000000000000000000000006044820152606401610c80565b33600090815260e060209081526040808320805460ff1916600117905560df90915290205480611a7d5760405162461bcd60e51b815260206004820152601060248201527f4e6f7468696e6720746f20636c61696d000000000000000000000000000000006044820152606401610c80565b33600081815260df6020908152604080832083905560cc5481517fa9059cbb000000000000000000000000000000000000000000000000000000008152600481019590955260248501869052905192936001600160a01b039091169263a9059cbb92604480840193919291829003018187875af1158015611b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b269190614872565b905080611b755760405162461bcd60e51b815260206004820152601560248201527f546f6b656e207472616e73666572206661696c656400000000000000000000006044820152606401610c80565b6040805183815242602082015233917f9923b4306c6c030f2bdfbf156517d5983b87e15b96176da122cd4f2effa4ba7b910160405180910390a260019250505090565b611bc0613805565b60005b8181101561182157600060e26000858585818110611be357611be361481d565b9050602002016020810190611bf89190614367565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905580611c2a81614833565b915050611bc3565b611c3a613805565b8051825114611c8b5760405162461bcd60e51b815260206004820152601160248201527f4d69736d617463686564206172726179730000000000000000000000000000006044820152606401610c80565b611c9760da6000614239565b611ca360d96000614239565b6000805b8351811015611e0a576000838281518110611cc457611cc461481d565b602002602001015111611d3f5760405162461bcd60e51b815260206004820152602160248201527f50657263656e74616765206d7573742062652067726561746572207468616e2060448201527f30000000000000000000000000000000000000000000000000000000000000006064820152608401610c80565b828181518110611d5157611d5161481d565b602002602001015182611d64919061485f565b915060da848281518110611d7a57611d7a61481d565b602090810291909101810151825460018101845560009384529190922001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909216919091179055825160d990849083908110611dd957611dd961481d565b6020908102919091018101518254600181018455600093845291909220015580611e0281614833565b915050611ca7565b50806064146118215760405162461bcd60e51b815260206004820152601f60248201527f546f74616c2070657263656e74616765206d75737420657175616c20313030006044820152606401610c80565b6000611e66826123b3565b9050611e7764e8d4a51000826147fb565b92915050565b611e85613805565b60d05460d780546001810182556000919091527f8a012a6de2943a5aa4d77acf5e695d4456760a3f1f30a5d6dc2079599187a071015560db54600160a01b900460ff1615611ed557611ed5613904565b60d460000160cf5481548110611eed57611eed61481d565b906000526020600020015460d0541015611fcb5760cf54600003611f595760c95460d89060d460000160cf5481548110611f2957611f2961481d565b9060005260206000200154611f3e919061484c565b81546001810183556000928352602090922090910155611fa3565b60d05460d89060d460000160cf5481548110611f7757611f7761481d565b9060005260206000200154611f8c919061484c565b815460018101835560009283526020909220909101555b60d460000160cf5481548110611fbb57611fbb61481d565b60009182526020909120015460d0555b60cf8054906000611fdb83614833565b9190505550565b611fea613805565b6001600160a01b0381166120405760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420726566657272616c20636f6e7472616374000000000000006044820152606401610c80565b60e4805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b612077613805565b61104d6000613c53565b60da818154811061209157600080fd5b6000918252602090912001546001600160a01b0316905081565b6120b3613805565b61104d613cb2565b6120c3613805565b60005b8181101561182157600060e160008585858181106120e6576120e661481d565b90506020020160208101906120fb9190614367565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061212d81614833565b9150506120c6565b61213d613805565b60cb54421161218e5760405162461bcd60e51b815260206004820152601860248201527f50726573616c65206973207374696c6c206f6e676f696e6700000000000000006044820152606401610c80565b60cc546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa1580156121f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612214919061488f565b9050600081116122665760405162461bcd60e51b815260206004820152601f60248201527f4e6f2072656d61696e696e6720746f6b656e7320746f207769746864726177006044820152606401610c80565b60cc546001600160a01b031663a9059cbb6122896065546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156122d6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5e9190614872565b60008060de60009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612350573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237491906148c2565b505050915050806402540be400611e779190614906565b612393613805565b60cf9190915560d055565b6123a6613805565b610e5e60d4826003614257565b600080600060d0546000146123ca5760d0546123ce565b60c9545b905060ce548411156124225760405162461bcd60e51b815260206004820181905260248201527f416d6f756e742065786365656473206d617820746f6b656e7320746f206275796044820152606401610c80565b60d460000160cf548154811061243a5761243a61481d565b90600052602060002001548185612451919061485f565b118061247f575060d460020160cf54815481106124705761247061481d565b90600052602060002001544210155b156126dc5760d4546124939060019061484c565b60cf54106124e35760405162461bcd60e51b815260206004820152600c60248201527f57726f6e6720706172616d7300000000000000000000000000000000000000006044820152606401610c80565b60d460020160cf54815481106124fb576124fb61481d565b906000526020600020015442106126285760cf5460d49061251d90600161485f565b8154811061252d5761252d61481d565b90600052602060002001548460d460006003811061254d5761254d61481d565b0160cf54815481106125615761256161481d565b9060005260206000200154612576919061485f565b11156125ea5760405162461bcd60e51b815260206004820152602360248201527f43616e74205075726368617365204d6f726520696e20696e646976696475616c60448201527f20747800000000000000000000000000000000000000000000000000000000006064820152608401610c80565b60cf5460d5906125fb90600161485f565b8154811061260b5761260b61481d565b90600052602060002001548461262191906147e4565b915061270d565b60008160d4820160cf54815481106126425761264261481d565b9060005260206000200154612657919061484c565b60cf5490915060d59061266b90600161485f565b8154811061267b5761267b61481d565b90600052602060002001548186612692919061484c565b61269c91906147e4565b60d460010160cf54815481106126b4576126b461481d565b9060005260206000200154826126ca91906147e4565b6126d4919061485f565b92505061270d565b60d460010160cf54815481106126f4576126f461481d565b90600052602060002001548461270a91906147e4565b91505b5092915050565b606060d482600381106127295761272961481d565b0180548060200260200160405190810160405280929190818152602001828054801561277457602002820191906000526020600020905b815481526020019060010190808311612760575b50505050509050919050565b612788613805565b60005b8181101561182157600160e160008585858181106127ab576127ab61481d565b90506020020160208101906127c09190614367565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055806127f281614833565b91505061278b565b60d8818154811061280a57600080fd5b600091825260209091200154905081565b6000612825613805565b6001600160a01b03831661287b5760405162461bcd60e51b815260206004820152601260248201527f5a65726f20746f6b656e206164647265737300000000000000000000000000006044820152606401610c80565b60ca86905560cb85905560cc80546001600160a01b0385811673ffffffffffffffffffffffffffffffffffffffff19928316811790935560db80547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16600160a81b17905560dd80549186169190921681179091556040517f095ea7b30000000000000000000000000000000000000000000000000000000081526004810191909152600019602482015263095ea7b3906044016020604051808303816000875af115801561294e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129729190614872565b5060006001600160a01b0384166323b872dd336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018890526064016020604051808303816000875af11580156129d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129fc9190614872565b905080612a4b5760405162461bcd60e51b815260206004820152601560248201527f546f6b656e207472616e73666572206661696c656400000000000000000000006044820152606401610c80565b604080518681524260208201526001600160a01b038616917fdc9670dbabdd488b372eb16ebe49a39b3124a12cdffdcefbc89834a408bf8ff8910160405180910390a25060019695505050505050565b606060d8805480602002602001604051908101604052809291908181526020018280548015612ae957602002820191906000526020600020905b815481526020019060010190808311612ad5575b5050505050905090565b612afb613805565b6001600160a01b038116612b515760405162461bcd60e51b815260206004820152601660248201527f616464726573732063616e6e6f74206265207a65726f000000000000000000006044820152606401610c80565b60db805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000612b8a6138b1565b60cc546001600160a01b0316612be25760405162461bcd60e51b815260206004820152601460248201527f53616c6520746f6b656e206e6f742061646465640000000000000000000000006044820152606401610c80565b33600090815260e1602052604090205460ff1615612c425760405162461bcd60e51b815260206004820152601b60248201527f54686973204164647265737320697320426c61636b6c697374656400000000006044820152606401610c80565b60db54600160b01b900460ff1615612cb35733600090815260e2602052604090205460ff16612cb35760405162461bcd60e51b815260206004820152601e60248201527f55736572206e6f742077686974656c697374656420666f72207374616b6500006044820152606401610c80565b33600090815260df602052604090205480612d105760405162461bcd60e51b815260206004820152601060248201527f4e6f7468696e6720746f207374616b65000000000000000000000000000000006044820152606401610c80565b60dd546001600160a01b03166391c61966336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015612d6a57600080fd5b505af1158015612d7e573d6000803e3d6000fd5b5050505060df6000612d8d3390565b6001600160a01b031681526020810191909152604001600090812055336001600160a01b03167ffa4ec67f9254455933eb145bae864b26f29dd0a7bbb76eb11e4d6b8b9b184c2b8242604051612ded929190918252602082015260400190565b60405180910390a2600191505090565b612e05613805565b6064811115612e565760405162461bcd60e51b815260206004820152601c60248201527f50657263656e746167652063616e6e6f742065786365656420313030000000006044820152606401610c80565b60e355565b60008360ca544210158015612e72575060cb544211155b612ebe5760405162461bcd60e51b815260206004820152601760248201527f496e76616c69642074696d6520666f7220627579696e670000000000000000006044820152606401610c80565b60008111612f0e5760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642073616c6520616d6f756e74000000000000000000000000006044820152606401610c80565b612f166138b1565b600260015403612f685760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610c80565b60026001556000612f78866123b3565b90508560c96000828254612f8c919061485f565b9091555060009050612fa364e8d4a51000836147fb565b905060d054600014612fc7578660d06000828254612fc1919061485f565b90915550505b600060d05460c95411612fdc5760d054612fe0565b60c9545b905060d460000160cf5481548110612ffa57612ffa61481d565b9060005260206000200154811180613034575060d460020160cf54815481106130255761302561481d565b90600052602060002001544210155b1561316e5760d460020160cf54815481106130515761305161481d565b90600052602060002001544210613094578760d460000160cf548154811061307b5761307b61481d565b9060005260206000200154613090919061485f565b60d0555b60db54600160a01b900460ff16156130ae576130ae613904565b600060d4810160cf54815481106130c7576130c761481d565b9060005260206000200154821161311657888260d460000160cf54815481106130f2576130f261481d565b9060005260206000200154613107919061484c565b613111919061484c565b613119565b60005b60d880546001818101835560009283527f5320ad99a619a90804cd2efe3a5cf0ac1ac5c41ad9ff2c61cf699efdad77109690910183905560cf8054939450909290919061316790849061485f565b9091555050505b86156132e15760db54600160b01b900460ff16156131e55733600090815260e2602052604090205460ff166131e55760405162461bcd60e51b815260206004820152601e60248201527f55736572206e6f742077686974656c697374656420666f72207374616b6500006044820152606401610c80565b60dd546001600160a01b03166391c619663360cd54613204908c6147e4565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561324a57600080fd5b505af115801561325e573d6000803e3d6000fd5b505050508760d36000828254613274919061485f565b909155505060dc546001600160a01b031688336001600160a01b03167f6f225532a9c33b023b8e48247ad8df9d98f132ae17c769b97ff22d2b278fa73a8587426040516132d4939291909283526020830191909152604082015260600190565b60405180910390a4613376565b60cd546132ee90896147e4565b33600090815260df60205260408120805490919061330d90849061485f565b909155505060dc546001600160a01b031688336001600160a01b03167f4d8aead3491b7eba4b5c7a65fc17e493b9e63f9e433522fc5f6a85a168fc9d3685874260405161336d939291909283526020830191909152604082015260600190565b60405180910390a45b8260d16000828254613388919061485f565b909155505060dc546000906001600160a01b031663dd62ed3e336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604401602060405180830381865afa1580156133ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613410919061488f565b9050808311156134885760405162461bcd60e51b815260206004820152602160248201527f4d616b65207375726520746f2061646420656e6f75676820616c6c6f77616e6360448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610c80565b6001600160a01b038716158015906134a957506001600160a01b0387163314155b80156134bf575060e4546001600160a01b031615155b1561365d576000606460e354856134d691906147e4565b6134e091906147fb565b90506134ec818561484c565b60dc549094506001600160a01b03166323b872dd3360e45460405160e084901b6001600160e01b03191681526001600160a01b03928316600482015291166024820152604481018490526064016020604051808303816000875af1158015613558573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061357c9190614872565b6135ee5760405162461bcd60e51b815260206004820152602960248201527f55534454207472616e7366657220746f20726566657272616c20636f6e74726160448201527f6374206661696c656400000000000000000000000000000000000000000000006064820152608401610c80565b60e4546040516322752acd60e11b81526001600160a01b038a811660048301526000602483015260448201849052909116906344ea559a90606401600060405180830381600087803b15801561364357600080fd5b505af1158015613657573d6000803e3d6000fd5b50505050505b6116a483613cef565b60d7818154811061280a57600080fd5b60d4826003811061368657600080fd5b01818154811061369557600080fd5b90600052602060002001600091509150505481565b6136b2613805565b60db8054911515600160b01b027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff909216919091179055565b6136f3613805565b60005b8181101561182157600160e260008585858181106137165761371661481d565b905060200201602081019061372b9190614367565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790558061375d81614833565b9150506136f6565b61376d613805565b6001600160a01b0381166137e95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c80565b6137f281613c53565b50565b60d9818154811061280a57600080fd5b6065546001600160a01b0316331461104d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c80565b613867614161565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60975460ff161561104d5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610c80565b60005b60cf5460d654613917919061484c565b8110156137f25760d25461392b90826147e4565b613935904261485f565b60cf5460d69061394690849061485f565b815481106139565761395661481d565b6000918252602090912001558061396c81614833565b915050613907565b60da546000036139ec5760db546001600160a01b03166139d65760405162461bcd60e51b815260206004820152601660248201527f5061796d656e742077616c6c6574206e6f7420736574000000000000000000006044820152606401610c80565b60db546137f2906001600160a01b031682613adb565b6000805b60da54811015613a84576000606460d98381548110613a1157613a1161481d565b906000526020600020015485613a2791906147e4565b613a3191906147fb565b9050613a6460da8381548110613a4957613a4961481d565b6000918252602090912001546001600160a01b031682613adb565b613a6e818461485f565b9250508080613a7c90614833565b9150506139f0565b506000613a91828461484c565b1115610e5e5760da8054610e5e9190613aac9060019061484c565b81548110613abc57613abc61481d565b6000918252602090912001546001600160a01b0316613adb838561484c565b80471015613b2b5760405162461bcd60e51b815260206004820152600b60248201527f4c6f772062616c616e63650000000000000000000000000000000000000000006044820152606401610c80565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613b78576040519150601f19603f3d011682016040523d82523d6000602084013e613b7d565b606091505b50509050806118215760405162461bcd60e51b815260206004820152601260248201527f455448205061796d656e74206661696c656400000000000000000000000000006044820152606401610c80565b600054610100900460ff16613c4b5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c80565b61104d6141b3565b606580546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b613cba6138b1565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586138943390565b60da54600003613e655760db546001600160a01b0316613d515760405162461bcd60e51b815260206004820152601660248201527f5061796d656e742077616c6c6574206e6f7420736574000000000000000000006044820152606401610c80565b60dc546000906001600160a01b03163360db546040516001600160a01b039283166024820152911660448201526064810184905260840160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b17905251613dd29190614952565b6000604051808303816000865af19150503d8060008114613e0f576040519150601f19603f3d011682016040523d82523d6000602084013e613e14565b606091505b5050905080610e5e5760405162461bcd60e51b815260206004820152601460248201527f546f6b656e207061796d656e74206661696c65640000000000000000000000006044820152606401610c80565b6000805b60da54811015613ffe576000606460d98381548110613e8a57613e8a61481d565b906000526020600020015485613ea091906147e4565b613eaa91906147fb565b60dc549091506000906001600160a01b03163360da8581548110613ed057613ed061481d565b6000918252602090912001546040516001600160a01b039283166024820152911660448201526064810184905260840160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b17905251613f4a9190614952565b6000604051808303816000865af19150503d8060008114613f87576040519150601f19603f3d011682016040523d82523d6000602084013e613f8c565b606091505b5050905080613fdd5760405162461bcd60e51b815260206004820152601460248201527f546f6b656e207061796d656e74206661696c65640000000000000000000000006044820152606401610c80565b613fe7828561485f565b935050508080613ff690614833565b915050613e69565b50600061400b828461484c565b1115610e5e5760dc546000906001600160a01b03163360da80546140319060019061484c565b815481106140415761404161481d565b6000918252602090912001546001600160a01b0316614060858761484c565b6040516001600160a01b039384166024820152929091166044830152606482015260840160408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b179052516140ce9190614952565b6000604051808303816000865af19150503d806000811461410b576040519150601f19603f3d011682016040523d82523d6000602084013e614110565b606091505b50509050806118215760405162461bcd60e51b815260206004820152601460248201527f546f6b656e207061796d656e74206661696c65640000000000000000000000006044820152606401610c80565b60975460ff1661104d5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c80565b600054610100900460ff166142305760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c80565b61104d33613c53565b50805460008255906000526020600020908101906137f291906142a7565b8260038101928215614297579160200282015b8281111561429757825180516142879184916020909101906142bc565b509160200191906001019061426a565b506142a3929150614303565b5090565b5b808211156142a357600081556001016142a8565b8280548282559060005260206000209081019282156142f7579160200282015b828111156142f75782518255916020019190600101906142dc565b506142a39291506142a7565b808211156142a35760006143178282614239565b50600101614303565b80151581146137f257600080fd5b60006020828403121561434057600080fd5b8135610f8081614320565b80356001600160a01b038116811461436257600080fd5b919050565b60006020828403121561437957600080fd5b610f808261434b565b6000806040838503121561439557600080fd5b50508035926020909101359150565b6000602082840312156143b657600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156143f6576143f66143bd565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715614425576144256143bd565b604052919050565b600067ffffffffffffffff821115614447576144476143bd565b5060051b60200190565b600082601f83011261446257600080fd5b813560206144776144728361442d565b6143fc565b82815260059290921b8401810191818101908684111561449657600080fd5b8286015b848110156144b1578035835291830191830161449a565b509695505050505050565b6000602082840312156144ce57600080fd5b813567ffffffffffffffff8111156144e557600080fd5b6144f184828501614451565b949350505050565b60008060006060848603121561450e57600080fd5b83359250602084013561452081614320565b915061452e6040850161434b565b90509250925092565b6000806040838503121561454a57600080fd5b6145538361434b565b91506145616020840161434b565b90509250929050565b6000806020838503121561457d57600080fd5b823567ffffffffffffffff8082111561459557600080fd5b818501915085601f8301126145a957600080fd5b8135818111156145b857600080fd5b8660208260051b85010111156145cd57600080fd5b60209290920196919550909350505050565b600080604083850312156145f257600080fd5b823567ffffffffffffffff8082111561460a57600080fd5b818501915085601f83011261461e57600080fd5b8135602061462e6144728361442d565b82815260059290921b8401810191818101908984111561464d57600080fd5b948201945b83861015614672576146638661434b565b82529482019490820190614652565b9650508601359250508082111561468857600080fd5b5061469585828601614451565b9150509250929050565b600060208083850312156146b257600080fd5b823567ffffffffffffffff808211156146ca57600080fd5b818501915085601f8301126146de57600080fd5b6146e66143d3565b8060608401888111156146f857600080fd5b845b8181101561472c578035858111156147125760008081fd5b61471e8b828901614451565b8552509286019286016146fa565b509098975050505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561477257835183529284019291840191600101614756565b50909695505050505050565b600080600080600060a0868803121561479657600080fd5b8535945060208601359350604086013592506147b46060870161434b565b91506147c26080870161434b565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417611e7757611e776147ce565b60008261481857634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060018201614845576148456147ce565b5060010190565b81810381811115611e7757611e776147ce565b80820180821115611e7757611e776147ce565b60006020828403121561488457600080fd5b8151610f8081614320565b6000602082840312156148a157600080fd5b5051919050565b805169ffffffffffffffffffff8116811461436257600080fd5b600080600080600060a086880312156148da57600080fd5b6148e3866148a8565b94506020860151935060408601519250606086015191506147c2608087016148a8565b808202600082127f80000000000000000000000000000000000000000000000000000000000000008414161561493e5761493e6147ce565b8181058314821517611e7757611e776147ce565b6000825160005b818110156149735760208186018101518583015201614959565b50600092019182525091905056fea264697066735822122087dd63d7f1bca95af0f22e8a271064617880a51151a8554ae0c5a307896a7d5664736f6c63430008130033
Verified Source Code Full Match
Compiler: v0.8.19+commit.7dd6d404
EVM: paris
Optimization: Yes (1337 runs)
AggregatorV3Interface.sol 20 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// solhint-disable-next-line interface-starts-with-i
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(
uint80 _roundId
) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
OwnableUpgradeable.sol 95 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions 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);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
Initializable.sol 138 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}
PausableUpgradeable.sol 117 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
ReentrancyGuardUpgradeable.sol 75 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ReentrancyGuardUpgradeable is Initializable {
// 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;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_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;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
IERC20Upgradeable.sol 82 lines
// SPDX-License-Identifier: MIT
// 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 IERC20Upgradeable {
/**
* @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);
}
AddressUpgradeable.sol 195 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
ContextUpgradeable.sol 37 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
IReferralRewards.sol 6 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
interface IReferralRewards {
function addReward(address referrer, uint256 ethAmount, uint256 usdtAmount) external payable;
}
IStakingManager.sol 6 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
interface StakingManager {
function depositByPresale(address _user, uint256 _amount) external;
}
Presale.sol 554 lines
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
import "./interfaces/IStakingManager.sol";
import "./interfaces/IReferralRewards.sol";
contract Presale is Initializable, ReentrancyGuardUpgradeable, OwnableUpgradeable, PausableUpgradeable {
uint256 public totalTokensSold;
uint256 public startTime;
uint256 public endTime;
address public saleToken;
uint256 public baseDecimals;
uint256 public maxTokensToBuy;
uint256 public currentStep;
uint256 public checkPoint;
uint256 public usdRaised;
uint256 public timeConstant;
uint256 public totalBoughtAndStaked;
uint256[][3] public rounds;
uint256[] public prevCheckpoints;
uint256[] public remainingTokensTracker;
uint256[] public percentages;
address[] public wallets;
address public paymentWallet;
bool public dynamicTimeFlag;
bool public whitelistClaimOnly;
bool public stakingWhitelistStatus;
IERC20Upgradeable public USDTInterface;
StakingManager public stakingManagerInterface;
AggregatorV3Interface public priceFeed;
mapping(address => uint256) public userDeposits;
mapping(address => bool) public hasClaimed;
mapping(address => bool) public isBlacklisted;
mapping(address => bool) public isWhitelisted;
uint256 public referralRewardPercentage;
IReferralRewards public referralRewards;
event SaleTimeSet(uint256 _start, uint256 _end, uint256 timestamp);
event SaleTimeUpdated(bytes32 indexed key, uint256 prevValue, uint256 newValue, uint256 timestamp);
event TokensBought(address indexed user, uint256 indexed tokensBought, address indexed purchaseToken, uint256 amountPaid, uint256 usdEq, uint256 timestamp);
event TokensAdded(address indexed token, uint256 noOfTokens, uint256 timestamp);
event TokensClaimed(address indexed user, uint256 amount, uint256 timestamp);
event ClaimStartUpdated(uint256 prevValue, uint256 newValue, uint256 timestamp);
event MaxTokensUpdated(uint256 prevValue, uint256 newValue, uint256 timestamp);
event TokensBoughtAndStaked(address indexed user, uint256 indexed tokensBought, address indexed purchaseToken, uint256 amountPaid, uint256 usdEq, uint256 timestamp);
event TokensClaimedAndStaked(address indexed user, uint256 amount, uint256 timestamp);
/**
* @dev To initialize the contract with price feed address
*/
function initialize(address _priceFeed, address _usdtAddress) public initializer {
__Ownable_init(); // Initialize owner
priceFeed = AggregatorV3Interface(_priceFeed);
USDTInterface = IERC20Upgradeable(_usdtAddress);
baseDecimals = 1000000000000000000;
referralRewardPercentage = 15; // Default 15%
}
/**
* @dev To pause the presale
*/
function pause() external onlyOwner {
_pause();
}
/**
* @dev To unpause the presale
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* @dev To calculate the price in USD for given amount of tokens.
* @param _amount No of tokens
*/
function calculatePrice(uint256 _amount) public view returns (uint256) {
uint256 USDTAmount;
uint256 total = checkPoint == 0 ? totalTokensSold : checkPoint;
require(_amount <= maxTokensToBuy, "Amount exceeds max tokens to buy");
if (_amount + total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
require(currentStep < (rounds[0].length - 1), "Wrong params");
if (block.timestamp >= rounds[2][currentStep]) {
require(rounds[0][currentStep] + _amount <= rounds[0][currentStep + 1], "Cant Purchase More in individual tx");
USDTAmount = _amount * rounds[1][currentStep + 1];
} else {
uint256 tokenAmountForCurrentPrice = rounds[0][currentStep] - total;
USDTAmount = tokenAmountForCurrentPrice * rounds[1][currentStep] + (_amount - tokenAmountForCurrentPrice) * rounds[1][currentStep + 1];
}
} else USDTAmount = _amount * rounds[1][currentStep];
return USDTAmount;
}
/**
* @dev To update the sale times
* @param _startTime New start time
* @param _endTime New end time
*/
function changeSaleTimes(uint256 _startTime, uint256 _endTime) external onlyOwner {
require(_startTime > 0 || _endTime > 0, "Invalid parameters");
if (_startTime > 0) {
require(block.timestamp < startTime, "Sale already started");
require(block.timestamp < _startTime, "Sale time in past");
uint256 prevValue = startTime;
startTime = _startTime;
emit SaleTimeUpdated(bytes32("START"), prevValue, _startTime, block.timestamp);
}
if (_endTime > 0) {
require(_endTime > startTime, "Invalid endTime");
uint256 prevValue = endTime;
endTime = _endTime;
emit SaleTimeUpdated(bytes32("END"), prevValue, _endTime, block.timestamp);
}
}
/**
* @dev To get latest ETH price in 10**18 format
*/
function getLatestPrice() public view returns (uint256) {
(, int256 price, , , ) = priceFeed.latestRoundData();
price = price * (10 ** 10); // ETH/USD price with 18 decimals
return uint256(price);
}
function setSplits(address[] memory _wallets, uint256[] memory _percentages) public onlyOwner {
require(_wallets.length == _percentages.length, "Mismatched arrays");
delete wallets;
delete percentages;
uint256 totalPercentage = 0;
for (uint256 i = 0; i < _wallets.length; i++) {
require(_percentages[i] > 0, "Percentage must be greater than 0");
totalPercentage += _percentages[i];
wallets.push(_wallets[i]);
percentages.push(_percentages[i]);
}
require(totalPercentage == 100, "Total percentage must equal 100");
}
modifier checkSaleState(uint256 amount) {
require(block.timestamp >= startTime && block.timestamp <= endTime, "Invalid time for buying");
require(amount > 0, "Invalid sale amount");
_;
}
/**
* @dev To buy into a presale using USDT
* @param amount No of tokens to buy
* @param stake boolean flag for token staking
* @param referrer referrer address
*/
function buyWithUSDT(uint256 amount, bool stake, address referrer) external checkSaleState(amount) whenNotPaused nonReentrant returns (bool) {
uint256 usdPrice = calculatePrice(amount);
totalTokensSold += amount;
uint256 price = usdPrice / (10 ** 12);
if (checkPoint != 0) checkPoint += amount;
uint256 total = totalTokensSold > checkPoint ? totalTokensSold : checkPoint;
if (total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
if (block.timestamp >= rounds[2][currentStep]) {
checkPoint = rounds[0][currentStep] + amount;
}
if (dynamicTimeFlag) {
manageTimeDiff();
}
uint256 unsoldTokens = total > rounds[0][currentStep] ? 0 : rounds[0][currentStep] - total - amount;
remainingTokensTracker.push(unsoldTokens);
currentStep += 1;
}
if (stake) {
if (stakingWhitelistStatus) {
require(isWhitelisted[_msgSender()], "User not whitelisted for stake");
}
stakingManagerInterface.depositByPresale(_msgSender(), amount * baseDecimals);
totalBoughtAndStaked += amount;
emit TokensBoughtAndStaked(_msgSender(), amount, address(USDTInterface), price, usdPrice, block.timestamp);
} else {
userDeposits[_msgSender()] += (amount * baseDecimals);
emit TokensBought(_msgSender(), amount, address(USDTInterface), price, usdPrice, block.timestamp);
}
usdRaised += usdPrice;
uint256 ourAllowance = USDTInterface.allowance(_msgSender(), address(this));
require(price <= ourAllowance, "Make sure to add enough allowance");
// referral rewards
if (referrer != address(0) && referrer != _msgSender() && address(referralRewards) != address(0)) {
uint256 referralReward = (price * referralRewardPercentage) / 100;
price -= referralReward;
require(
USDTInterface.transferFrom(_msgSender(), address(referralRewards), referralReward),
"USDT transfer to referral contract failed"
);
referralRewards.addReward(referrer, 0, referralReward);
}
splitUSDTValue(price);
return true;
}
/**
* @dev To buy into a presale using ETH
* @param amount No of tokens to buy
* @param stake boolean flag for token staking
* @param referrer referrer address
*/
function buyWithEth(uint256 amount, bool stake, address referrer) external payable checkSaleState(amount) whenNotPaused nonReentrant returns (bool) {
uint256 usdPrice = calculatePrice(amount);
uint256 ethAmount = (usdPrice * baseDecimals) / getLatestPrice();
require(msg.value >= ethAmount, "Less payment");
uint256 excess = msg.value - ethAmount;
totalTokensSold += amount;
if (checkPoint != 0) checkPoint += amount;
uint256 total = totalTokensSold > checkPoint ? totalTokensSold : checkPoint;
if (total > rounds[0][currentStep] || block.timestamp >= rounds[2][currentStep]) {
if (block.timestamp >= rounds[2][currentStep]) {
checkPoint = rounds[0][currentStep] + amount;
}
if (dynamicTimeFlag) {
manageTimeDiff();
}
uint256 unsoldTokens = total > rounds[0][currentStep] ? 0 : rounds[0][currentStep] - total - amount;
remainingTokensTracker.push(unsoldTokens);
currentStep += 1;
}
if (stake) {
if (stakingWhitelistStatus) {
require(isWhitelisted[_msgSender()], "User not whitelisted for stake");
}
stakingManagerInterface.depositByPresale(_msgSender(), amount * baseDecimals);
totalBoughtAndStaked += amount;
emit TokensBoughtAndStaked(_msgSender(), amount, address(0), ethAmount, usdPrice, block.timestamp);
} else {
userDeposits[_msgSender()] += (amount * baseDecimals);
emit TokensBought(_msgSender(), amount, address(0), ethAmount, usdPrice, block.timestamp);
}
usdRaised += usdPrice;
// Handle referral rewards
if (referrer != address(0) && referrer != _msgSender() && address(referralRewards) != address(0)) {
uint256 referralReward = (ethAmount * referralRewardPercentage) / 100;
ethAmount -= referralReward; // Deduct referral reward from total
referralRewards.addReward{value: referralReward}(referrer, referralReward, 0);
}
splitETHValue(ethAmount);
if (excess > 0) sendValue(payable(_msgSender()), excess);
return true;
}
/**
* @dev Helper funtion to get ETH price for given amount
* @param amount No of tokens to buy
*/
function ethBuyHelper(uint256 amount) external view returns (uint256 ethAmount) {
uint256 usdPrice = calculatePrice(amount);
ethAmount = (usdPrice * baseDecimals) / getLatestPrice();
}
/**
* @dev Helper funtion to get USDT price for given amount
* @param amount No of tokens to buy
*/
function usdtBuyHelper(uint256 amount) external view returns (uint256 usdPrice) {
usdPrice = calculatePrice(amount);
usdPrice = usdPrice / (10 ** 12);
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Low balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "ETH Payment failed");
}
function splitETHValue(uint256 _amount) internal {
if (wallets.length == 0) {
require(paymentWallet != address(0), "Payment wallet not set");
sendValue(payable(paymentWallet), _amount);
} else {
uint256 tempCalc;
for (uint256 i = 0; i < wallets.length; i++) {
uint256 amountToTransfer = (_amount * percentages[i]) / 100;
sendValue(payable(wallets[i]), amountToTransfer);
tempCalc += amountToTransfer;
}
if ((_amount - tempCalc) > 0) {
sendValue(payable(wallets[wallets.length - 1]), _amount - tempCalc);
}
}
}
function splitUSDTValue(uint256 _amount) internal {
if (wallets.length == 0) {
require(paymentWallet != address(0), "Payment wallet not set");
(bool success, ) = address(USDTInterface).call(abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), paymentWallet, _amount));
require(success, "Token payment failed");
} else {
uint256 tempCalc;
for (uint256 i = 0; i < wallets.length; i++) {
uint256 amountToTransfer = (_amount * percentages[i]) / 100;
(bool success, ) = address(USDTInterface).call(abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), wallets[i], amountToTransfer));
require(success, "Token payment failed");
tempCalc += amountToTransfer;
}
if ((_amount - tempCalc) > 0) {
(bool success, ) = address(USDTInterface).call(abi.encodeWithSignature("transferFrom(address,address,uint256)", _msgSender(), wallets[wallets.length - 1], _amount - tempCalc));
require(success, "Token payment failed");
}
}
}
/**
* @dev To set the claim start time and sale token address by the owner
* @param _startTime start time
* @param _endTime start time
* @param noOfTokens no of tokens to add to the contract
* @param _saleToken sale toke address
*/
function startClaim(uint256 _startTime, uint256 _endTime, uint256 noOfTokens, address _saleToken, address _stakingManagerAddress) external onlyOwner returns (bool) {
require(_saleToken != address(0), "Zero token address");
startTime = _startTime;
endTime = _endTime;
saleToken = _saleToken;
whitelistClaimOnly = true;
stakingManagerInterface = StakingManager(_stakingManagerAddress);
IERC20Upgradeable(_saleToken).approve(_stakingManagerAddress, type(uint256).max);
bool success = IERC20Upgradeable(_saleToken).transferFrom(_msgSender(), address(this), noOfTokens);
require(success, "Token transfer failed");
emit TokensAdded(_saleToken, noOfTokens, block.timestamp);
return true;
}
/**
* @dev To set status for claim whitelisting
* @param _status bool value
*/
function setStakingWhitelistStatus(bool _status) external onlyOwner {
stakingWhitelistStatus = _status;
}
function changeMaxTokensToBuy(uint256 _maxTokensToBuy) external onlyOwner {
require(_maxTokensToBuy > 0, "Zero max tokens to buy value");
uint256 prevValue = maxTokensToBuy;
maxTokensToBuy = _maxTokensToBuy;
emit MaxTokensUpdated(prevValue, _maxTokensToBuy, block.timestamp);
}
function changeRoundsData(uint256[][3] memory _rounds) external onlyOwner {
rounds = _rounds;
}
/**
* @dev Set referral rewards contract
*/
function setReferralRewardsContract(address _referralRewards) external onlyOwner {
require(_referralRewards != address(0), "Invalid referral contract");
referralRewards = IReferralRewards(_referralRewards);
}
/**
* @dev Set referral reward percentage
*/
function setReferralRewardPercentage(uint256 _percentage) external onlyOwner {
require(_percentage <= 100, "Percentage cannot exceed 100");
referralRewardPercentage = _percentage;
}
/**
* @dev To add users to blacklist which restricts blacklisted users from claiming
* @param _usersToBlacklist addresses of the users
*/
function blacklistUsers(address[] calldata _usersToBlacklist) external onlyOwner {
for (uint256 i = 0; i < _usersToBlacklist.length; i++) {
isBlacklisted[_usersToBlacklist[i]] = true;
}
}
/**
* @dev To remove users from blacklist which restricts blacklisted users from claiming
* @param _userToRemoveFromBlacklist addresses of the users
*/
function removeFromBlacklist(address[] calldata _userToRemoveFromBlacklist) external onlyOwner {
for (uint256 i = 0; i < _userToRemoveFromBlacklist.length; i++) {
isBlacklisted[_userToRemoveFromBlacklist[i]] = false;
}
}
/**
* @dev To add users to whitelist which restricts users from claiming if claimWhitelistStatus is true
* @param _usersToWhitelist addresses of the users
*/
function whitelistUsers(address[] calldata _usersToWhitelist) external onlyOwner {
for (uint256 i = 0; i < _usersToWhitelist.length; i++) {
isWhitelisted[_usersToWhitelist[i]] = true;
}
}
/**
* @dev To remove users from whitelist which restricts users from claiming if claimWhitelistStatus is true
* @param _userToRemoveFromWhitelist addresses of the users
*/
function removeFromWhitelist(address[] calldata _userToRemoveFromWhitelist) external onlyOwner {
for (uint256 i = 0; i < _userToRemoveFromWhitelist.length; i++) {
isWhitelisted[_userToRemoveFromWhitelist[i]] = false;
}
}
/**
* @dev To set status for claim whitelisting
* @param _status bool value
*/
function setClaimWhitelistStatus(bool _status) external onlyOwner {
whitelistClaimOnly = _status;
}
/**
* @dev To set payment wallet address
* @param _newPaymentWallet new payment wallet address
*/
function changePaymentWallet(address _newPaymentWallet) external onlyOwner {
require(_newPaymentWallet != address(0), "address cannot be zero");
paymentWallet = _newPaymentWallet;
}
/**
* @dev To manage time gap between two rounds
*/
function manageTimeDiff() internal {
for (uint256 i; i < rounds[2].length - currentStep; i++) {
rounds[2][currentStep + i] = block.timestamp + i * timeConstant;
}
}
/**
* @dev To set time constant for manageTimeDiff()
* @param _timeConstant time in <days>*24*60*60 format
*/
function setTimeConstant(uint256 _timeConstant) external onlyOwner {
timeConstant = _timeConstant;
}
/**
* @dev To get array of round details at once
* @param _no array index
*/
function roundDetails(uint256 _no) external view returns (uint256[] memory) {
return rounds[_no];
}
/**
* @dev To increment the rounds from backend
*/
function incrementCurrentStep() external onlyOwner {
prevCheckpoints.push(checkPoint);
if (dynamicTimeFlag) {
manageTimeDiff();
}
if (checkPoint < rounds[0][currentStep]) {
if (currentStep == 0) {
remainingTokensTracker.push(rounds[0][currentStep] - totalTokensSold);
} else {
remainingTokensTracker.push(rounds[0][currentStep] - checkPoint);
}
checkPoint = rounds[0][currentStep];
}
currentStep++;
}
/**
* @dev To change details of the round
* @param _step round for which you want to change the details
* @param _checkpoint token tracker amount
*/
function setCurrentStep(uint256 _step, uint256 _checkpoint) external onlyOwner {
currentStep = _step;
checkPoint = _checkpoint;
}
/**
* @dev To set time shift functionality on/off
* @param _dynamicTimeFlag bool value
*/
function setDynamicTimeFlag(bool _dynamicTimeFlag) external onlyOwner {
dynamicTimeFlag = _dynamicTimeFlag;
}
/**
* @dev Function to return remainingTokenTracker Array
*/
function trackRemainingTokens() external view returns (uint256[] memory) {
return remainingTokensTracker;
}
/**
* @dev To update remainingTokensTracker Array
* @param _unsoldTokens input parameters in uint256 array format
*/
function setRemainingTokensArray(uint256[] memory _unsoldTokens) public onlyOwner {
require(_unsoldTokens.length != 0, "cannot update invalid values");
delete remainingTokensTracker;
for (uint256 i = 0; i < _unsoldTokens.length; i++) {
remainingTokensTracker.push(_unsoldTokens[i]);
}
}
function withdrawRemainingTokens() external onlyOwner {
require(block.timestamp > endTime, "Presale is still ongoing");
uint256 remainingTokens = IERC20Upgradeable(saleToken).balanceOf(address(this));
require(remainingTokens > 0, "No remaining tokens to withdraw");
IERC20Upgradeable(saleToken).transfer(owner(), remainingTokens);
}
/**
* @dev To claim tokens after claiming starts
*/
function claim() external whenNotPaused returns (bool) {
require(saleToken != address(0), "Sale token not added");
require(!isBlacklisted[_msgSender()], "This Address is Blacklisted");
if (whitelistClaimOnly) {
require(isWhitelisted[_msgSender()], "User not whitelisted for claim");
}
require(block.timestamp >= endTime, "Claim has not started yet");
require(!hasClaimed[_msgSender()], "Already claimed");
hasClaimed[_msgSender()] = true;
uint256 amount = userDeposits[_msgSender()];
require(amount > 0, "Nothing to claim");
delete userDeposits[_msgSender()];
bool success = IERC20Upgradeable(saleToken).transfer(_msgSender(), amount);
require(success, "Token transfer failed");
emit TokensClaimed(_msgSender(), amount, block.timestamp);
return true;
}
function claimAndStake() external whenNotPaused returns (bool) {
require(saleToken != address(0), "Sale token not added");
require(!isBlacklisted[_msgSender()], "This Address is Blacklisted");
if (stakingWhitelistStatus) {
require(isWhitelisted[_msgSender()], "User not whitelisted for stake");
}
uint256 amount = userDeposits[_msgSender()];
require(amount > 0, "Nothing to stake");
stakingManagerInterface.depositByPresale(_msgSender(), amount);
delete userDeposits[_msgSender()];
emit TokensClaimedAndStaked(_msgSender(), amount, block.timestamp);
return true;
}
}
Read Contract
USDTInterface 0xf597573f → address
baseDecimals 0x33f76178 → uint256
calculatePrice 0xae104265 → uint256
checkPoint 0xcff805ab → uint256
currentStep 0x5bc34f71 → uint256
dynamicTimeFlag 0x1fa2bc92 → bool
endTime 0x3197cbb6 → uint256
ethBuyHelper 0x29a5a0b6 → uint256
getLatestPrice 0x8e15f473 → uint256
hasClaimed 0x73b2e80e → bool
isBlacklisted 0xfe575a87 → bool
isWhitelisted 0x3af32abf → bool
maxTokensToBuy 0x9cfa0f7c → uint256
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
paymentWallet 0xe32204dd → address
percentages 0xf8858386 → uint256
prevCheckpoints 0xe19648db → uint256
priceFeed 0x741bef1a → address
referralRewardPercentage 0x920a253e → uint256
referralRewards 0x995deaba → address
remainingTokensTracker 0xc23326f3 → uint256
roundDetails 0xba166a39 → uint256[]
rounds 0xe6da9213 → uint256
saleToken 0xe985e367 → address
stakingManagerInterface 0x38646608 → address
stakingWhitelistStatus 0x232e95be → bool
startTime 0x78e97925 → uint256
timeConstant 0x43568eae → uint256
totalBoughtAndStaked 0x7f6fb253 → uint256
totalTokensSold 0x63b20117 → uint256
trackRemainingTokens 0xc8adff01 → uint256[]
usdRaised 0xeadd94ec → uint256
usdtBuyHelper 0x63e40879 → uint256
userDeposits 0x0ba36dcd → uint256
wallets 0x7ad71f72 → address
whitelistClaimOnly 0x53d99207 → bool
Write Contract 29 functions
These functions modify contract state and require a wallet transaction to execute.
blacklistUsers 0xbb3d676a
address[] _usersToBlacklist
buyWithEth 0x4151848f
uint256 amount
bool stake
address referrer
returns: bool
buyWithUSDT 0xd1690fec
uint256 amount
bool stake
address referrer
returns: bool
changeMaxTokensToBuy 0x278c278b
uint256 _maxTokensToBuy
changePaymentWallet 0xcad00556
address _newPaymentWallet
changeRoundsData 0xa6d42e4e
uint256[][3] _rounds
changeSaleTimes 0x0dc9c838
uint256 _startTime
uint256 _endTime
claim 0x4e71d92d
No parameters
returns: bool
claimAndStake 0xcb1a4fc0
No parameters
returns: bool
incrementCurrentStep 0x641046f4
No parameters
initialize 0x485cc955
address _priceFeed
address _usdtAddress
pause 0x8456cb59
No parameters
removeFromBlacklist 0x89daf799
address[] _userToRemoveFromBlacklist
removeFromWhitelist 0x548db174
address[] _userToRemoveFromWhitelist
renounceOwnership 0x715018a6
No parameters
setClaimWhitelistStatus 0x1ddc6091
bool _status
setCurrentStep 0x9a89c1fb
uint256 _step
uint256 _checkpoint
setDynamicTimeFlag 0x0a200fc7
bool _dynamicTimeFlag
setReferralRewardPercentage 0xcedcc6da
uint256 _percentage
setReferralRewardsContract 0x6b4052fc
address _referralRewards
setRemainingTokensArray 0x2dc358e8
uint256[] _unsoldTokens
setSplits 0x5ddc5688
address[] _wallets
uint256[] _percentages
setStakingWhitelistStatus 0xeac0d115
bool _status
setTimeConstant 0x23a8f1c0
uint256 _timeConstant
startClaim 0xc6ae7178
uint256 _startTime
uint256 _endTime
uint256 noOfTokens
address _saleToken
address _stakingManagerAddress
returns: bool
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
whitelistUsers 0xedec5f27
address[] _usersToWhitelist
withdrawRemainingTokens 0x8afbf669
No parameters
Recent Transactions
No transactions found for this address