Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x16cF768b9b82270eD438467f3aB8D76e395aA57d
Balance 0 ETH
Nonce 1
Code Size 9595 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9595 bytes
0x6101e0604052600436101561001357600080fd5b60003560e01c80630188a4fd14611cd15780630828d2f814611c8557806318eac30614611c675780632533a5f614611c1b57806325ea750f14611bf8578063285c9dd514611bd25780632be11ae214611a1057806331165a7d146119c457806333aac1d41461198b5780633ccfd60b146116a25780633f4ba83a1461163157806342dfcb5e146115fa57806343405b18146115d957806347e7ef24146114435780634f15bba7146114255780635c975abb146113ff5780635e5b077d1461134757806363d9df851461131e5780636e573eba14611300578063704b6c0214611292578063715018a6146112355780637419f19014611217578063747cfc3a146111cb57806379ee54f7146111a05780638456cb591461113e5780638a6876ad146111205780638bd8b014146110a15780638da5cb5b1461107857806391c6196614610e4a578063a29f481c14610dcb578063a54cd6db14610d4e578063a6a11bb114610d30578063a9bbd11414610cc2578063b2819be814610ca1578063b614f4a214610c83578063b73d0d0a14610c37578063b78d93961461089c578063bd58d6fa14610647578063be76f9861461053e578063c8b3e887146104f2578063c95c16af146104b3578063cc1b63d514610492578063cddb3e7b1461041c578063d0fcb8f8146103fe578063dcfd7ad2146103e0578063df7b633c14610394578063e50374df14610376578063e985e3671461034d578063f2fde38b146102c3578063f3cd8e81146102a5578063f851a4401461027c5763fafcca8c1461025957600080fd5b34610277576000366003190112610277576020600f54604051908152f35b600080fd5b34610277576000366003190112610277576005546040516001600160a01b039091168152602090f35b34610277576000366003190112610277576020600d54604051908152f35b34610277576020366003190112610277576102dc611d16565b6102e46120fc565b6001600160a01b0316801561033757600180546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b631e4fbdf760e01b600052600060045260246000fd5b34610277576000366003190112610277576002546040516001600160a01b039091168152602090f35b34610277576000366003190112610277576020601054604051908152f35b34610277576020366003190112610277577fc67d60849559aa3d9636c81a4ee073da3427317c06135ef6b66831589c29477860206004356103d36120fc565b80600855604051908152a1005b34610277576000366003190112610277576020600754604051908152f35b34610277576000366003190112610277576020600954604051908152f35b34610277576020366003190112610277576001600160a01b0361043d611d16565b16600052601160205260c06040600020805490600181015490600281015460038201549060ff6005600485015494015416936040519586526020860152604085015260608401526080830152151560a0820152f35b34610277576020366003190112610277576104ab6120fc565b600435600e55005b34610277576020366003190112610277576001600160a01b036104d4611d16565b166000526012602052602060ff604060002054166040519015158152f35b34610277576020366003190112610277577f0218abee81fd4282658cc4524b502a64f45bca9da5ad0ecee61931c72b4195ca60206004356105316120fc565b80601055604051908152a1005b34610277576040366003190112610277576004356001600160401b0381116102775761056e903690600401611d2c565b906024356001600160401b0381116102775761058e903690600401611d2c565b6105999291926120fc565b8084036106025760005b8481106105ac57005b6105b78183866120d8565b3590811515809203610277576001916001600160a01b036105e16105dc848a896120d8565b6120e8565b16600052601260205260406000209060ff80198354169116179055016105a3565b60405162461bcd60e51b815260206004820152601a60248201527f506172616d6574657273206c656e677468206d69736d617463680000000000006044820152606490fd5b34610277576040366003190112610277576004356024359060018060a01b036005541633148015610888575b1561084d5760095482101580610842575b80610837575b8061082c575b156107ee57600354811115806107e2575b156107ac5760407f447f79ea09db992a8472747637bb5a47a14bc7c3054722a6e121c1b2e8569c05916106d660085482611f1b565b9381600855806009556106e7612167565b82519182526020820152a160ff60015460a81c16806107a3575b61070757005b600254600480546040516370a0823160e01b81526001600160a01b0391821692810183905293921690602084602481855afa93841561079757600094610761575b506107588361075f951015611eda565b30916123d7565b005b93506020843d60201161078f575b8161077c60209383611e4d565b8101031261027757925192610758610748565b3d915061076f565b6040513d6000823e3d90fd5b50801515610701565b60405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606490fd5b506008548110156106a1565b60405162461bcd60e51b8152602060048201526016602482015275155c19185d19481d1a5b59481a5cc81a5b9d985b1a5960521b6044820152606490fd5b50600c548210610690565b50600f54821061068a565b50600e548211610684565b60405162461bcd60e51b815260206004820152601360248201527227b7363c9037bbb732b91037b91030b236b4b760691b6044820152606490fd5b506001546001600160a01b03163314610673565b346102775760c0366003190112610277576004356001600160401b038111610277576108cc903690600401611d2c565b60c052610140526024356001600160401b038111610277576108f2903690600401611d2c565b61018052610160526044356001600160401b03811161027757610919903690600401611d2c565b6101c0526101a0526064356001600160401b03811161027757610940903690600401611d2c565b61012052610100526084356001600160401b03811161027757610967903690600401611d2c565b60a4356001600160401b03811161027757610986903690600401611d2c565b60e052906109926120fc565b6109a360ff60015460a81c16611d5c565b6101805160c0511480610c29575b80610c1b575b80610c10575b80610c03575b15610bcc57600060a0525b60c05160a051106109e8576014805460ff19166001179055005b60a05160c051610140516001600160a01b0392610a08926105dc926120d8565b16600052601260205260ff60406000205416610b875760a05160c051610140516001600160a01b0392610a3e926105dc926120d8565b1660005260116020526040600020608052610a6f610a6560a05161018051610160516120d8565b3560805154611e81565b60805155610a8660a0516101c0516101a0516120d8565b3560016080510190815410610b6b575b50610aaa60a05161012051610100516120d8565b35610abc600260805101918254611e81565b9055610acb60a05182856120d8565b35610add600360805101918254611e81565b9055610aee60a05160e051846120d8565b35610b00600460805101918254611e81565b905560a05160c051610140516001600160a01b0392610b22926105dc926120d8565b1660005260126020526040600020600160ff19825416179055610b5a610b5160a05161018051610160516120d8565b35600754611e81565b600755600160a0510160a0526109ce565b610b7e60a0516101c0516101a0516120d8565b35905583610a96565b60405162461bcd60e51b815260206004820152601760248201527f5374616b657220616c726561647920696d706f727465640000000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600f60248201526e098cadccee8d040dad2e6dac2e8c6d608b1b6044820152606490fd5b5060e05160c051146109c3565b508060c051146109bd565b506101205160c051146109b7565b506101c05160c051146109b1565b34610277576020366003190112610277577f24a4de9632e651b4ed4ab74d57494231b6c0cb933214ef6b1575aa1ce489d76c6020600435610c766120fc565b80600a55604051908152a1005b34610277576000366003190112610277576020600854604051908152f35b3461027757602036600319011261027757610cba6120fc565b600435600d55005b3461027757602036600319011261027757610cdb611d16565b610ce36120fc565b6001600160a01b0316610cf7811515611fea565b600480546001600160a01b031916821790557f2971d9a2608887e4669a5ed341051b04123952d66306cc3c2aaba0aa3d4060cb600080a2005b34610277576000366003190112610277576020600c54604051908152f35b34610277576020366003190112610277576004356001600160401b03811161027757610d7e903690600401611d2c565b90610d876120fc565b60005b828110610d9357005b6001906001600160a01b03610dac6105dc8387876120d8565b166000526011602052600560406000200160ff19815416905501610d8a565b3461027757602036600319011261027757610de4611d16565b610dec6120fc565b610e0c60ff60015460a81c168080610e37575b8115610e2e575b50611fea565b600280546001600160a01b0319166001600160a01b0392909216919091179055005b90501583610e06565b6001600160a01b03841615159150610dff565b3461027757604036600319011261027757610e63611d16565b60243590610e6f612125565b610e77612147565b6004546001600160a01b0316330361102257610e97600e54421015611da8565b610ea4600f544210611f59565b600c54421015610fe857610eb9821515611f9e565b60018060a01b03811691826000526011602052604060002091825415610f61575b907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c92610f08602093612304565b5064e8d4a51000610f29610f1d848454611e81565b808455600b5490611e6e565b046003820155600142910155610f4181600754611e81565b600755610f5081600654611e81565b600655604051908152a26001600055005b906013549268010000000000000000841015610fd257610f08602093610fae8660017fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9801601355611f28565b81549060031b9089821b9160018060a01b03901b1916179055929350509250610eda565b634e487b7160e01b600052604160045260246000fd5b60405162461bcd60e51b8152602060048201526012602482015271436c61696d20697320617661696c61626c6560701b6044820152606490fd5b60405162461bcd60e51b815260206004820152602860248201527f54686973206d6574686f64206973206f6e6c7920666f722070726573616c652060448201526718dbdb9d1c9858dd60c21b6064820152608490fd5b34610277576000366003190112610277576001546040516001600160a01b039091168152602090f35b34610277576020366003190112610277576004356001600160401b038111610277576110d1903690600401611d2c565b906110da6120fc565b60005b8281106110e657005b6001906001600160a01b036110ff6105dc8387876120d8565b16600052601160205260056040600020018260ff19825416179055016110dd565b34610277576000366003190112610277576020600654604051908152f35b34610277576000366003190112610277576111576120fc565b61115f612147565b6001805460ff60a01b1916600160a01b1790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602090a1005b346102775760203660031901126102775760206111c36111be611d16565b612028565b604051908152f35b34610277576020366003190112610277577fc1f24b6e6cfecfc456ae1355c506e9fbb29485247c32cf417b11030145b2491a602060043561120a6120fc565b80600f55604051908152a1005b34610277576000366003190112610277576020600e54604051908152f35b346102775760003660031901126102775761124e6120fc565b600180546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610277576020366003190112610277576112ab611d16565b6112b36120fc565b6001600160a01b03166112c7811515611fea565b600580546001600160a01b031916821790557f54e4612788f90384e6843298d7854436f3a585b2c3831ab66abf1de63bfa6c2d600080a2005b34610277576000366003190112610277576020600b54604051908152f35b34610277576000366003190112610277576004546040516001600160a01b039091168152602090f35b346102775760003660031901126102775760e0806040516113688282611e4d565b3690376040518181018181106001600160401b03821117610fd2576040526006548152600754602082015260085460408201526009546060820152600c54608082015260135460a082015260ff601454166000146113f65760ff60015b1660c0820152604051906000825b600782106113e057505050f35b60208060019285518152019301910190916113d3565b60ff60006113c5565b3461027757600036600319011261027757602060ff60015460a01c166040519015158152f35b34610277576000366003190112610277576020600a54604051908152f35b346102775760403660031901126102775761145c611d16565b602435611467612125565b61146f612147565b61148060ff60015460a81c16611d5c565b6004546001600160a01b0316331480156115c7575b156115825761157b916114ac600e54421015611da8565b6114b9600f544210611f59565b6114c7600c54421015611ded565b6114d2821515611f9e565b6001600160a01b038116600081815260116020526040902090916114fd906114f8612167565b612304565b5064e8d4a51000611512610f1d858454611e81565b04600382015560014291015561152a82600754611e81565b60075561153982600854611e81565b6008557fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c6020604051848152a2600254309033906001600160a01b03166123d7565b6001600055005b60405162461bcd60e51b815260206004820152601c60248201527f4f6e6c792075736572206f722070726573616c6520616c6c6f776564000000006044820152606490fd5b50336001600160a01b03831614611495565b34610277576020366003190112610277576115f26120fc565b600435600355005b34610277576020366003190112610277576020611618600435611f28565b905460405160039290921b1c6001600160a01b03168152f35b346102775760003660031901126102775761164a6120fc565b60015460ff8160a01c16156116915760ff60a01b19166001556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602090a1005b638dfc202b60e01b60005260046000fd5b34610277576000366003190112610277576116bb612125565b6116c3612147565b6116d460ff60015460a81c16611d5c565b6116e2600e54421015611da8565b600c546116f181421015611ded565b33600052601160205260406000206040519161170c83611e32565b8154835260ff6005600184015493846020870152600281015460408701526003810154606087015260048101546080870152015416151560a0840152600d5491620151808302928084046201518014901517156119755761176e834292611e81565b11159182611960575b505015611900578061178d602492511515611e8e565b6002546040516370a0823160e01b81523060048201529260209184919082906001600160a01b03165afa918215610797576000926118ca575b506117d761157b9282511115611eda565b6117df612167565b6117e833612200565b336000526011602052600060056040822082815582600182015582600282015582600382015582600482015501556118238251600754611f1b565b6007556118338251600854611f1b565b60085580611881575b5080516040519081527f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436460203392a260025490519033906001600160a01b0316612395565b6118c4906040518181527fdaaebb9609cb2f719c59c9d334be287bf4def107ad3dec4a6f90d8abaa94c73c60203392a260025433906001600160a01b0316612395565b8261183c565b91506020823d6020116118f8575b816118e560209383611e4d565b81010312610277579051906117d76117c6565b3d91506118d8565b60405162461bcd60e51b815260206004820152603260248201527f596f7520617265206e6f7420616c6c6f77656420746f207769746864726177206044820152716265666f7265206c6f636b65642074696d6560701b6064820152608490fd5b42925061196c91611e81565b11158280611777565b634e487b7160e01b600052601160045260246000fd5b3461027757602036600319011261027757600435801515809103610277576119b16120fc565b60ff801960145416911617601455600080f35b34610277576020366003190112610277577f0e9b46e0126fd83f21428afabceb65db1b97fb0b7e9a4b13fcb509e889e33a3f6020600435611a036120fc565b80600955604051908152a1005b3461027757600036600319011261027757611a29612125565b611a31612147565b611a4260ff60015460a81c16611d5c565b611a50600e54421015611da8565b600c54611a5f81421015611ded565b336000526011602052604060002060405191611a7a83611e32565b8154835260ff6005600184015493846020870152600281015460408701526003810154606087015260048101546080870152015416151560a0840152600d54916201518083029280840462015180149015171561197557611adc834292611e81565b11159182611bbd575b505015611b5e57611af890511515611e8e565b611b00612167565b611b0933612200565b80611b15576001600055005b611b58906040518181527fdaaebb9609cb2f719c59c9d334be287bf4def107ad3dec4a6f90d8abaa94c73c60203392a260025433906001600160a01b0316612395565b8061157b565b60405162461bcd60e51b815260206004820152603160248201527f596f7520617265206e6f7420616c6c6f77656420746f2068617276657374206260448201527065666f7265206c6f636b65642074696d6560781b6064820152608490fd5b429250611bc991611e81565b11158280611ae5565b3461027757600036600319011261027757602060ff60015460a81c166040519015158152f35b3461027757600036600319011261027757602060ff601454166040519015158152f35b34610277576020366003190112610277577fdd0d2291cab08c638170770eb9326ea87a21ce2966f8d0df4b2d651ecfb75b226020600435611c5a6120fc565b80600c55604051908152a1005b34610277576000366003190112610277576020600354604051908152f35b34610277576020366003190112610277577f1ee30dbaa8a6e1c74991222940175a060c2270f20bc748cebc1ffd6c8c0a21cc6020600435611cc46120fc565b80600b55604051908152a1005b346102775760203660031901126102775760043580151580910361027757611cf76120fc565b6001805460ff60a81b191660a89290921b60ff60a81b16919091179055005b600435906001600160a01b038216820361027757565b9181601f84011215610277578235916001600160401b038311610277576020808501948460051b01011161027757565b15611d6357565b60405162461bcd60e51b815260206004820152601c60248201527f54686973206973206e6f7420746865206d61696e206e6574776f726b000000006044820152606490fd5b15611daf57565b60405162461bcd60e51b815260206004820152601660248201527514dd185ada5b99c81a185cdb89dd081cdd185c9d195960521b6044820152606490fd5b15611df457565b60405162461bcd60e51b8152602060048201526016602482015275436c61696d206973206e6f7420617661696c61626c6560501b6044820152606490fd5b60c081019081106001600160401b03821117610fd257604052565b90601f801991011681019081106001600160401b03821117610fd257604052565b8181029291811591840414171561197557565b9190820180921161197557565b15611e9557565b60405162461bcd60e51b815260206004820152601b60248201527f416d6f756e74207374616b65642063616e2774206265207a65726f00000000006044820152606490fd5b15611ee157565b60405162461bcd60e51b8152602060048201526012602482015271084c2d8c2dcc6ca40dcdee840cadcdeeaced60731b6044820152606490fd5b9190820391821161197557565b601354811015611f4357601360005260206000200190600090565b634e487b7160e01b600052603260045260246000fd5b15611f6057565b60405162461bcd60e51b815260206004820152601660248201527514dd185ada5b99c81a185cc81899595b88195b99195960521b6044820152606490fd5b15611fa557565b60405162461bcd60e51b815260206004820152601c60248201527f4465706f73697420616d6f756e742063616e2774206265207a65726f000000006044820152606490fd5b15611ff157565b60405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606490fd5b600854156120d2576120cf90612048600b5461204261241b565b90611e81565b9060018060a01b031660005260116020526120c760406000209164e8d4a510006120be6040519261207884611e32565b855480855260018701546020860152600287015460408601526003870154946060810195865260a060ff600560048b01549a608085019b8c520154161515910152611e6e565b04905190611f1b565b905190611e81565b90565b50600090565b9190811015611f435760051b0190565b356001600160a01b03811681036102775790565b6001546001600160a01b0316330361211057565b63118cdaa760e01b6000523360045260246000fd5b600260005414612136576002600055565b633ee5aeb560e01b60005260046000fd5b60ff60015460a01c1661215657565b63d93c066560e01b60005260046000fd5b600854156121d4576121776124be565b1561217e57565b61219161218961241b565b600b54611e81565b600b55600f548042116000146121a7575b600a55565b50600a546121b44261248e565b62015180810290808204620151801490151715611975576121a291611e81565b6121dd4261248e565b62015180810290808204620151801490151715611975576121a290600a54611e81565b6001600160a01b03166000908152601160205260409020600581015460ff166122bf5764e8d4a510006122378254600b5490611e6e565b04906003810191612249835482611f1b565b9283612259575b50505050600090565b60028301612268858254611e81565b905555600c54421015806122b7575b1561229d5760040180548061228b57505090565b6122989060009293611e81565b915590565b60046122ac9101918254611e81565b905538808080612250565b506001612277565b60405162461bcd60e51b815260206004820152601b60248201527f54686973206164647265737320697320626c61636b6c697374656400000000006044820152606490fd5b6001600160a01b03166000908152601160205260409020600581015460ff166122bf5764e8d4a5100061233b8254600b5490611e6e565b0490600381019161234d835482611f1b565b928361235c5750505050600090565b6002830161236b858254611e81565b905555600c544210158061238d571561229d5760040180548061228b57505090565b506000612277565b60405163a9059cbb60e01b60208201526001600160a01b0390921660248301526044808301939093529181526123d5916123d0606483611e4d565b6124ea565b565b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526123d5916123d0608483611e4d565b600f5480421160001461247c5761243461243d9161248e565b60105490611e6e565b64e8d4a5100081029080820464e8d4a51000149015171561197557600854908115612466570490565b634e487b7160e01b600052601260045260246000fd5b5061243d6124894261248e565b612434565b6124966124be565b6120d257600a54908082116124b75762015180916124b391611f1b565b0490565b5050600090565b600c544210156124e5576009544281116120d2576124e0620151809142611f1b565b101590565b600090565b906000602091828151910182855af115610797576000513d61253c57506001600160a01b0381163b155b61251b5750565b635274afe760e01b60009081526001600160a01b0391909116600452602490fd5b6001141561251456fea2646970667358221220b675fc387e32aa893cfad6a05fc4e4eb81ead78040228c2605557fc3ebd78a3a64736f6c634300081a0033

Verified Source Code Full Match

Compiler: v0.8.26+commit.8a97fa7a EVM: paris Optimization: Yes (200 runs)
Staking.sol 759 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract StakingManager is ReentrancyGuard, Ownable, Pausable {
    using SafeERC20 for IERC20; // Wrappers around ERC20 operations that throw on failure

    // Digest
    string private constant DIGEST = "2025-01-30"; // Compile version

    // Main
    bool public isMainNetwork; // Set true if its the main network where the coin will be deployed
    IERC20 public saleToken; // Token to be staked and rewarded
    uint256 public saleTokenTotalMinted; // Total sale tokens minted;
    address public presaleContract; // Presale contract address
    address public admin; // Admin address

    // Sum
    uint256 public tokensStakedByPresale; // Total tokens staked by presale
    uint256 public tokensStakedByNetwork; // Total tokens staked by this network
    uint256 public tokensStakedTotal; // Total tokens staked in all networks
    uint256 public tokensStakedTotalLastUpdateTime; // Time the tokens staked total was updated

    // Pool
    uint256 public poolLastDayReward; // Pool last day the pool had their rewards calculated
    uint256 public poolAccumulatedRewardsPerShare; // Pool accumulated rewards per share times REWARDS PRECISION, it saves the total rewards generated in the pool until the last processment, per share means the value is relative to all coins stake

    // Claim
    uint256 public claimStartTime; // Users are allowed to claim after this time in epoch
    uint256 public claimLockDays; // To lock the tokens in contract for a definite time IN SECONDS, this is the min time needed to keep in stake before can claim again.

    // Stake
    uint256 public stakeStartTime; // At this time the stake will be started - 1 July 2024 15:00:00 - 1719846000
    uint256 public stakeEndTime; // At this time the stake will be stopped - 1 July 2025 15:00:00 - 1751382000.   --- DIFF 31536000
    uint256 public stakeRewardsTokensPerDay; // Number of reward tokens minted per day

    // Constants
    uint256 private constant REWARDS_PRECISION = 1e12; // A big number to perform mul and div operations
    uint256 private constant DAY_SECONDS = 86400; // Number of seconds of a day

    // Staking user for a pool
    struct PoolStaker {
        uint256 stakerAmount; // The amount of tokens the user has staked
        uint256 stakerStakedTime; // The time the tokens was staked
        uint256 stakerRewardsHarvested; // Total amount of tokens rewards the user harvested
        uint256 stakerRewardsDebt; // Total amount the user cant get as reward (relative to poolAccumulatedRewardsPerShare)
        uint256 stakerRewardsLocked; // Total amount of locked rewards
        bool stakerIsBlacklisted; // Mark if user is blacklisted
    }

    // Staker address => PoolStaker
    mapping(address => PoolStaker) public poolStakers; // Save data of all stakers
    mapping(address => bool) public imported;
    address[] private addressStakersPresale; // Save address of stakers that join in the presale
    bool public isImportDone;

    // Events
    event Deposit(address indexed user, uint256 amount);
    event Withdraw(address indexed user, uint256 amount);
    event HarvestRewards(address indexed user, uint256 amount);
    event TokensStakedTotalUpdated(uint256 amount);
    event TokensStakedTotalUpdated(uint256 amount, uint256 updateTime);
    event TokensStakedTotalLastUpdateTimeUpdated(uint256 updateTime);
    event AdminUpdated(address indexed pAdmin);
    event PresaleContractUpdated(address indexed pPresaleContract);
    event ClaimStartTimeUpdated(uint256 pClaimStartTime);
    event StakeEndTimeUpdated(uint256 pStakeEndTime);
    event StakeRewardsTokensPerDayUpdated(uint256 pStakeRewardsTokensPerDay);
    event PoolLastDayRewardUpdated(uint256 pPoolLastDayReward);
    event PoolAccumulatedRewardsPerShareUpdated(uint256 poolAccumulatedRewardsPerShare);

    // Modifiers
    modifier onlyPresale() {
        require(msg.sender == presaleContract, "This method is only for presale contract");
        _;
    }

    modifier onlyOwnerOrAdmin() {
        require(msg.sender == admin || msg.sender == owner(), "Only owner or admin");
        _;
    }

    /**
     * @dev Initializes the contract and sets initial parameters
     *
     * @param _isMainNetwork True if this is the network where the presale token will be deployed
     * @param _saleToken Address of the token
     * @param _presaleContract Address of the presale
     * @param _admin Address of admin
     * @param _stakeStartTime Time the stake will be started
     * @param _stakeEndTime Time the stake will be stopped
     * @param _stakeRewardsTokensPerDay Number of reward tokens minted per day
     * @param _claimStartTime Time where the claim will be available
     * @param _claimLockDays To lock the tokens in contract for a definite time IN DAYS, this is the min time needed to keep in stake before can claim again
     * @param _saleTokenTotalMinted Total of sale tokens minted
     */
    constructor(
        bool _isMainNetwork,
        address _saleToken,
        address _presaleContract,
        address _admin,
        uint256 _stakeStartTime,
        uint256 _stakeEndTime,
        uint256 _stakeRewardsTokensPerDay,
        uint256 _claimStartTime,
        uint256 _claimLockDays,
        uint256 _saleTokenTotalMinted
    ) Ownable(msg.sender) {
        require(_presaleContract != address(0), "Presale contract is required");
        require(_admin != address(0), "Admin address is required");
        require(_stakeStartTime < _stakeEndTime, "Presale end time must be greater than start time");
        require(_stakeEndTime > block.timestamp, "Presale end time must be in the future");
        require(_stakeRewardsTokensPerDay > 0, "Stake rewards per day should be bigger than ZERO");

        isMainNetwork = _isMainNetwork;
        if (_isMainNetwork) saleToken = IERC20(_saleToken);
        presaleContract = _presaleContract;
        admin = _admin;
        stakeStartTime = _stakeStartTime;
        stakeEndTime = _stakeEndTime;
        stakeRewardsTokensPerDay = _stakeRewardsTokensPerDay;
        claimStartTime = _claimStartTime;
        claimLockDays = _claimLockDays;
        poolLastDayReward = stakeStartTime; // Initialize
        tokensStakedTotalLastUpdateTime = stakeStartTime; // Initialize
        saleTokenTotalMinted = _saleTokenTotalMinted;
    }

    /**
     * @dev Deposit tokens to the pool from outside the presale
     *
     * This function allows users to deposit tokens they already have to the staking pool,
     * when the presale already finished.
     * It moves the deposited tokens to the staking pool.
     *
     * @param pAmount The amount of tokens to deposit
     *
     * Requirements:
     * - Contract must be on the main network
     * - Staking must have started
     * - Staking must not have ended
     * - Deposit amount cannot be zero
     * - User must not be blacklisted
     *
     * Effects:
     * - Updates the pool stakers' information
     * - Updates the current staker's information
     * - Updates the total tokens staked by the network
     * - Transfers the deposited tokens from the user to the contract
     *
     * Emits a Deposit event with the user's address and the amount deposited
     */
    function deposit(address pUserAddress, uint256 pAmount) external nonReentrant whenNotPaused {
        require(isMainNetwork, "This is not the main network");
        require(msg.sender == presaleContract || msg.sender == pUserAddress, "Only user or presale allowed");
        require(block.timestamp >= stakeStartTime, "Staking hasn't started");
        require(block.timestamp < stakeEndTime, "Staking has been ended");
        require(block.timestamp >= claimStartTime, "Claim is not available");
        require(pAmount > 0, "Deposit amount can't be zero");

        PoolStaker storage staker = poolStakers[pUserAddress];

        updatePoolRewards();

        // Update pool stakers
        harvestRewards(pUserAddress, false);

        // Update current staker
        staker.stakerAmount += pAmount;
        staker.stakerRewardsDebt = (staker.stakerAmount * poolAccumulatedRewardsPerShare) / REWARDS_PRECISION;
        staker.stakerStakedTime = block.timestamp;

        // Update pool
        tokensStakedByNetwork += pAmount;
        tokensStakedTotal += pAmount;

        // Deposit tokens
        emit Deposit(pUserAddress, pAmount);

        // Receive a deposit of coins to this address
        saleToken.safeTransferFrom(msg.sender, address(this), pAmount);
    }

    /**
     * @dev Deposit tokens to the pool by the presale contract
     *
     * Do not move the coins in the presale stage.
     * At the end of the presale, the total amount sold in all networks with the total supply of staking coins is moved here so it can be withdraw.
     * Do not move the coins in the presale stage
     *
     * @param pUserAddress The address of the user who is depositing tokens
     * @param pAmount The amount of tokens to deposit
     *
     * Requirements:
     * - Staking must have started
     * - Staking must not have ended
     * - Deposit amount cannot be zero
     * - User must not be blacklisted
     *
     * Effects:
     * - Updates the pool stakers' information
     * - Updates the current staker's information
     * - Updates the total tokens staked by the network
     *
     * Emits a Deposit event with the user's address and the amount deposited
     */
    function depositByPresale(address pUserAddress, uint256 pAmount) external nonReentrant whenNotPaused onlyPresale {
        require(block.timestamp >= stakeStartTime, "Staking hasn't started");
        require(block.timestamp < stakeEndTime, "Staking has been ended");
        require(block.timestamp < claimStartTime, "Claim is available");
        require(pAmount > 0, "Deposit amount can't be zero");

        PoolStaker storage staker = poolStakers[pUserAddress];

        //Add user if its his first interaction
        if (staker.stakerAmount == 0) addressStakersPresale.push(pUserAddress);

        // Update pool stakers
        harvestRewards(pUserAddress, false);

        // Update current staker
        staker.stakerAmount += pAmount;
        staker.stakerRewardsDebt = (staker.stakerAmount * poolAccumulatedRewardsPerShare) / REWARDS_PRECISION;
        staker.stakerStakedTime = block.timestamp;

        // Update pool
        tokensStakedByNetwork += pAmount;
        tokensStakedByPresale += pAmount;

        // Deposit tokens
        emit Deposit(pUserAddress, pAmount);
    }

    /**
     * @dev Withdraw all staked tokens from the pool
     *
     * Requirements:
     * - Contract must be on the main network
     * - Staking must have started
     * - Staking must not have ended
     * - Claim must have started
     * - User withdraw amount cannot be zero
     * - User claim lock time should have expired
     * - User must not be blacklisted
     *
     * Effects:
     * - Pool staker's information is deleted
     * - Total tokens staked by the network is updated
     * - Withdraw tokens are transferred back to the user
     *
     * Emits a Withdraw event with the user's address and the amount of the withdraw
     */
    function withdraw() external nonReentrant whenNotPaused {
        require(isMainNetwork, "This is not the main network");
        require(block.timestamp >= stakeStartTime, "Staking hasn't started");
        require(block.timestamp >= claimStartTime, "Claim is not available");

        PoolStaker memory staker = poolStakers[msg.sender];
        require(
            staker.stakerStakedTime + (claimLockDays * DAY_SECONDS) <= block.timestamp && claimStartTime + (claimLockDays * DAY_SECONDS) <= block.timestamp,
            "You are not allowed to withdraw before locked time"
        );
        require(staker.stakerAmount > 0, "Amount staked can't be zero");
        require(saleToken.balanceOf(address(this)) >= staker.stakerAmount, "Balance not enough");

        updatePoolRewards();

        // Pay rewards
        uint256 _rewardsToHarvest = harvestRewards(msg.sender, true);

        // Delete staker
        delete poolStakers[msg.sender];

        // Update pool
        tokensStakedByNetwork -= staker.stakerAmount;
        tokensStakedTotal -= staker.stakerAmount;

        // If there are rewards to harvest send it to the user
        if (_rewardsToHarvest > 0) {
            emit HarvestRewards(msg.sender, _rewardsToHarvest);
            saleToken.safeTransfer(msg.sender, _rewardsToHarvest);
        }

        // Withdraw tokens
        emit Withdraw(msg.sender, staker.stakerAmount);
        saleToken.safeTransfer(msg.sender, staker.stakerAmount);
    }

    /**
     * @dev Harvests the rewards for the user
     *
     * This function allows the user to harvest their accumulated rewards from staking in the pool.
     * It calculates the rewards that the user has earned since the last update,
     * records the amount as harvested rewards, updates the user's rewards debt, and optionally transfers the rewards to the user.
     *
     * Requirements:
     * - Contract must be on the main network
     * - Staking must have started
     * - Staking must not have ended
     * - Claim must have started
     * - User staked amount cannot be zero
     * - User claim lock time should have expired
     * - User must not be blacklisted
     *
     * Effects:
     * - Calculates and transfers the user's rewards
     * - Updates the user's harvested rewards, rewards debt, and locked rewards
     *
     * Emits a HarvestRewards event with the user's address and the amount of rewards harvested
     */
    function harvestRewards() external nonReentrant whenNotPaused {
        require(isMainNetwork, "This is not the main network");
        require(block.timestamp >= stakeStartTime, "Staking hasn't started");
        require(block.timestamp >= claimStartTime, "Claim is not available");

        PoolStaker memory staker = poolStakers[msg.sender];
        require(
            staker.stakerStakedTime + (claimLockDays * DAY_SECONDS) <= block.timestamp && claimStartTime + (claimLockDays * DAY_SECONDS) <= block.timestamp,
            "You are not allowed to harvest before locked time"
        );
        require(staker.stakerAmount > 0, "Amount staked can't be zero");

        updatePoolRewards();

        uint256 _rewardsToHarvest = harvestRewards(msg.sender, true);

        // If there are rewards to harvest send it to the user
        if (_rewardsToHarvest > 0) {
            emit HarvestRewards(msg.sender, _rewardsToHarvest);
            saleToken.safeTransfer(msg.sender, _rewardsToHarvest);
        }
    }

    function harvestRewards(address pUserAddress, bool pHarvestNow) private returns (uint256) {
        PoolStaker storage staker = poolStakers[pUserAddress];
        require(!staker.stakerIsBlacklisted, "This address is blacklisted");

        uint256 _rewardsDebtUpdate = (staker.stakerAmount * poolAccumulatedRewardsPerShare) / REWARDS_PRECISION;
        uint256 _rewardsToHarvest = _rewardsDebtUpdate - staker.stakerRewardsDebt;

        if (_rewardsToHarvest > 0) {
            staker.stakerRewardsHarvested += _rewardsToHarvest;
            staker.stakerRewardsDebt = _rewardsDebtUpdate;

            // If claim is available and harvest now flag is true
            if (block.timestamp >= claimStartTime && pHarvestNow) {
                if (staker.stakerRewardsLocked > 0) {
                    _rewardsToHarvest += staker.stakerRewardsLocked;
                    staker.stakerRewardsLocked = 0;
                }

                // Return the value of the rewards to harvest that will be sent to the user
                return _rewardsToHarvest;

                // Sum the rewards
            } else {
                staker.stakerRewardsLocked += _rewardsToHarvest;
            }
        }

        return 0;
    }

    /**
     * @dev Checks if the tokensStakedTotalLastUpdateTime has expired
     *
     * This function checks if the difference between the current block timestamp and the tokensStakedTotalLastUpdateTime
     * is greater than or equal to one day, indicating that the tokensStakedTotalLastUpdateTime has expired.
     *
     * @return A boolean value indicating whether the tokensStakedTotalLastUpdateTime has expired (true) or not (false)
     */
    function isTokensStakedTotalLastUpdateTimeExpired() private view returns (bool) {
        if (block.timestamp >= claimStartTime) return false; // If the claim is active
        if (tokensStakedTotalLastUpdateTime > block.timestamp) return false;
        return (block.timestamp - tokensStakedTotalLastUpdateTime) >= DAY_SECONDS;
    }

    /**
     * @dev Calculates the number of days that have passed since the last reward was processed in the pool.
     *
     * This function determines the number of days that have elapsed between the current timestamp and the
     * timestamp when the last reward was processed in the pool. If the tokensStakedTotalLastUpdateTime has expired,
     * the number of days passed is calculated up to the current block timestamp. Otherwise, it returns 0.
     *
     * @param pTimestamp The timestamp for which the number of days passed since the last reward is being calculated
     *
     * @return The number of days that have passed since the last reward was processed in the pool
     */
    function calcDaysPassedSinceLastReward(uint256 pTimestamp) private view returns (uint256) {
        if (isTokensStakedTotalLastUpdateTimeExpired()) return 0;
        if (poolLastDayReward > pTimestamp) return 0;
        return (pTimestamp - poolLastDayReward) / DAY_SECONDS;
    }

    /**
     * @dev Updates the pool rewards based on the current timestamp and the tokens staked in the pool
     *
     * If the tokensStakedTotal is zero, the function increments the poolLastDayReward by the number of days passed
     * since the last reward was processed.
     *
     * If tokensStakedTotalLastUpdateTime is not expired updates the poolAccumulatedRewardsPerShare by incrementing
     * the total of rewards that was generated until this moment in the pool based on the total of coins staked and
     * updates the poolLastDayReward checking if the stakeEndTime or adding the number of days that passed.
     *
     * Effects:
     * - Updates the pool accumulated rewards per share
     * - Updates the last day the pool had their rewards calculated
     *
     */
    function updatePoolRewards() private {
        if (tokensStakedTotal == 0) {
            poolLastDayReward += (calcDaysPassedSinceLastReward(block.timestamp) * DAY_SECONDS); // Increment with the days passed that didnt generate any reward
            return;
        }

        if (!isTokensStakedTotalLastUpdateTimeExpired()) {
            poolAccumulatedRewardsPerShare += getPoolAccumulatedRewardsPerShare(); // This increments the total of rewards that was generated until this moment in the pool based on the total of coins staked
            poolLastDayReward = block.timestamp > stakeEndTime ? stakeEndTime : poolLastDayReward + (calcDaysPassedSinceLastReward(block.timestamp) * DAY_SECONDS); // Update last day a reward was generated
        }
    }

    /**
     * @dev Calculates the rewards accumulated in the pool since the last update
     * by multiplying the number of blocks since the last update with the rewards tokens per block
     *
     * The REWARDS_PRECISION is needed to generate more precision on smaller numbers
     *
     * @return The accumulated rewards in the pool since the last update
     */
    function getPoolAccumulatedRewardsPerShare() private view returns (uint256) {
        uint256 _poolDaysSinceLastUpdate = block.timestamp > stakeEndTime ? calcDaysPassedSinceLastReward(stakeEndTime) : calcDaysPassedSinceLastReward(block.timestamp);
        uint256 _poolRewardsSinceLastUpdate = _poolDaysSinceLastUpdate * stakeRewardsTokensPerDay;
        return (_poolRewardsSinceLastUpdate * REWARDS_PRECISION) / tokensStakedTotal;
    }

    /**
     * @dev Calculates the rewards available for the user based on the amount staked,
     * accumulated rewards in the pool, and rewards debt.
     *
     * This function calculates the rewards available for the user by multiplying the
     * amount staked by the accumulated rewards per share, adjusting for the rewards debt
     * that the user already claimed. It also considers any rewards that are currently locked
     * and not available for withdraw.
     *
     * @param pUserAddress The address of the user for whom rewards are being calculated
     *
     * @return The total amount of rewards available for the user
     */
    function getRewards(address pUserAddress) external view returns (uint256) {
        if (tokensStakedTotal == 0) {
            return 0;
        }

        uint256 _accCalc = poolAccumulatedRewardsPerShare + getPoolAccumulatedRewardsPerShare();
        PoolStaker memory staker = poolStakers[pUserAddress];
        return ((staker.stakerAmount * _accCalc) / REWARDS_PRECISION) - staker.stakerRewardsDebt + staker.stakerRewardsLocked;
    }

    /**
     * @dev Get current total tokens staked details
     // Array of details 
     [0] -> TOTAL_TOKENS_STAKED_BY_PRESALE, 
     [1] -> TOTAL_TOKENS_STAKED_BY_NETWORK, 
     [2] -> TOTAL_TOKENS_STAKED_TOTAL, 
     [3] -> TOTAL_TOKENS_STAKED_TOTAL_LAST_UPDATE_TIME), 
     [4] -> CLAIM_START_TIME, 
     [5] -> STAKERS_LENGTH,
     [6] -> IS_IMPORT_DONE
     */
    function getTokensStakedDetails() external view returns (uint256[7] memory) {
        return [tokensStakedByPresale, tokensStakedByNetwork, tokensStakedTotal, tokensStakedTotalLastUpdateTime, claimStartTime, addressStakersPresale.length, isImportDone ? 1 : 0];
    }

    /**
     * @dev Set is main network on/off
     */
    function setIsMainNetwork(bool pIsMainNetwork) external onlyOwner {
        isMainNetwork = pIsMainNetwork;
    }

    /**
     * @dev Set sale token address
     */
    function setSaleToken(address pSaleToken) external onlyOwner {
        require((isMainNetwork && pSaleToken != address(0)) || !isMainNetwork, "Invalid address");
        saleToken = IERC20(pSaleToken);
    }

    /**
     * @dev Set sale token total minted
     */
    function setSaleTokenTotalMinted(uint256 pSaleTokenTotalMinted) external onlyOwner {
        saleTokenTotalMinted = pSaleTokenTotalMinted;
    }

    /**
     * @dev Set presale contract address
     */
    function setPresaleContract(address pPresaleContract) external onlyOwner {
        require(pPresaleContract != address(0), "Invalid address");
        presaleContract = pPresaleContract;
        emit PresaleContractUpdated(pPresaleContract);
    }

    /**
     * @dev Set admin address
     */
    function setAdmin(address pAdmin) external onlyOwner {
        require(pAdmin != address(0), "Invalid address");
        admin = pAdmin;
        emit AdminUpdated(pAdmin);
    }

    /**
     * @dev Set claim start time
     */
    function setClaimStartTime(uint256 pClaimStartTime) external onlyOwner {
        claimStartTime = pClaimStartTime;
        emit ClaimStartTimeUpdated(pClaimStartTime);
    }

    /**
     * @dev Set claim lock days
     */
    function setClaimLockDays(uint256 pClaimLockDays) external onlyOwner {
        claimLockDays = pClaimLockDays;
    }

    /**
     * @dev Set stake start time
     */
    function setStakeStartTime(uint256 pStakeStartTime) external onlyOwner {
        stakeStartTime = pStakeStartTime;
    }

    /**
     * @dev Set stake end time
     */
    function setStakeEndTime(uint256 pStakeEndTime) external onlyOwner {
        stakeEndTime = pStakeEndTime;
        emit StakeEndTimeUpdated(pStakeEndTime);
    }

    /**
     * @dev Set stake rewards tokens per day
     */
    function setStakeRewardsTokensPerDay(uint256 pStakeRewardsTokensPerDay) external onlyOwner {
        stakeRewardsTokensPerDay = pStakeRewardsTokensPerDay;
        emit StakeRewardsTokensPerDayUpdated(pStakeRewardsTokensPerDay);
    }

    /**
     * @dev Set tokens staked total
     */
    function setTokensStakedTotal(uint256 pAmount, uint256 pUpdateTime) external onlyOwnerOrAdmin {
        require(pUpdateTime >= tokensStakedTotalLastUpdateTime && pUpdateTime > stakeStartTime && pUpdateTime < stakeEndTime && pUpdateTime < claimStartTime, "Update time is invalid");
        require(pAmount <= saleTokenTotalMinted && pAmount >= tokensStakedTotal, "Invalid amount");
        uint256 tokensStakedTotalDiff = pAmount - tokensStakedTotal;
        tokensStakedTotal = pAmount;
        tokensStakedTotalLastUpdateTime = pUpdateTime; // Need to use a fixed time for everyday control.
        updatePoolRewards(); // Sincronize all networks pool rewards
        emit TokensStakedTotalUpdated(pAmount, pUpdateTime);
        if (isMainNetwork && tokensStakedTotalDiff > 0) {
            require(saleToken.balanceOf(presaleContract) >= tokensStakedTotalDiff, "Balance not enough");
            saleToken.safeTransferFrom(presaleContract, address(this), tokensStakedTotalDiff);
        }
    }

    /**
     * @dev Set tokens staked total
     */
    function setTokensStakedTotal(uint256 pAmount) external onlyOwner {
        tokensStakedTotal = pAmount;
        emit TokensStakedTotalUpdated(pAmount);
    }

    /**
     * @dev Set tokens staked total last update time
     */
    function setTokensStakedTotalLastUpdateTime(uint256 pUpdateTime) external onlyOwner {
        tokensStakedTotalLastUpdateTime = pUpdateTime;
        emit TokensStakedTotalLastUpdateTimeUpdated(pUpdateTime);
    }

    /**
     * @dev Set pool last day reward
     */
    function setPoolLastDayReward(uint256 pPoolLastDayReward) external onlyOwner {
        poolLastDayReward = pPoolLastDayReward;
        emit PoolLastDayRewardUpdated(pPoolLastDayReward);
    }

    /**
     * @dev Set pool accumulated rewards per share
     */
    function setPoolAccumulatedRewardsPerShare(uint256 pPoolAccumulatedRewardsPerShare) external onlyOwner {
        poolAccumulatedRewardsPerShare = pPoolAccumulatedRewardsPerShare;
        emit PoolAccumulatedRewardsPerShareUpdated(pPoolAccumulatedRewardsPerShare);
    }

    /**
     * @dev Pause the presale
     */
    function pause() external onlyOwner {
        _pause();
    }

    /**
     * @dev Unpause the presale
     */
    function unpause() external onlyOwner {
        _unpause();
    }

    /**
     * @dev Adds the specified users to the blacklist
     *
     * This function allows the contract owner to add the specified users to the blacklist, preventing them from participating in staking and claiming rewards.
     * Any user added to the blacklist will not be able to deposit, withdraw, or harvest rewards.
     *
     * @param pUsersList An array of addresses representing the users to be added to the blacklist
     *
     * Requirements:
     * - The function can only be called by the contract owner
     *
     * Effects:
     * - Updates the isBlacklisted flag for the specified users to true
     *
     */
    function usersBlacklistAdd(address[] calldata pUsersList) external onlyOwner {
        uint256 size = pUsersList.length;
        for (uint256 i = 0; i < size; i++) {
            PoolStaker storage staker = poolStakers[pUsersList[i]];
            staker.stakerIsBlacklisted = true;
        }
    }

    /**
     * @dev Removes the specified users from the blacklist
     *
     * This function allows the contract owner to remove the specified users from the blacklist, enabling them to participate in staking and claiming rewards again.
     * Any user removed from the blacklist will regain the ability to deposit, withdraw, and harvest rewards.
     *
     * @param pUsersList An array of addresses representing the users to be removed from the blacklist
     *
     * Requirements:
     * - The function can only be called by the contract owner
     *
     * Effects:
     * - Updates the isBlacklisted flag for the specified users to false
     */
    function usersBlacklistRemove(address[] calldata pUsersList) external onlyOwner {
        uint256 size = pUsersList.length;
        for (uint256 i = 0; i < size; i++) {
            PoolStaker storage staker = poolStakers[pUsersList[i]];
            staker.stakerIsBlacklisted = false;
        }
    }

    /**
     * @dev This function allows the contract owner or admin to retrieve the address of a staker from the list of stakers that joined during the presale
     *
     * @param pIndex The index of the staker's address in the array
     *
     * Requirements:
     * - Only the contract owner or admin can call this function
     *
     * @return The address of the staker at the specified index
     *
     */
    function getAddressStakersPresale(uint256 pIndex) external view returns (address) {
        return addressStakersPresale[pIndex];
    }

    /**
     * @dev Set imported value for a given address
     *
     * @param pAddresses address
     * @param pValues flag to indicate if address was imported or not
     */
    function setImported(address[] calldata pAddresses, bool[] calldata pValues) external onlyOwner {
        require(pAddresses.length == pValues.length, "Parameters length mismatch");

        uint256 size = pAddresses.length;
        for (uint256 i = 0; i < size; i++) {
            imported[pAddresses[i]] = pValues[i];
        }
    }

    /**
     * @dev Set is import done
     */
    function setIsImportDone(bool pIsImportDone) external onlyOwner {
        isImportDone = pIsImportDone;
    }

    /**
     * @dev Imports the staking data for multiple stakers into the pool
     *
     * This function allows the contract owner to import staking data for multiple stakers into the pool.
     * The function takes two arrays as inputs - one containing the addresses of the stakers and the
     * other containing the staking data for each staker. It then updates the staking information for
     * each staker in the pool based on the provided data.
     *
     * @param pStakersAddress An array of addresses representing the stakers for whom staking data is being imported
     * @param pAmount An array of PoolStaker structs containing the staking data for each respective staker
     * @param pStakedTime An array of PoolStaker structs containing the staking data for each respective staker
     * @param pRewardsHarvested An array of PoolStaker structs containing the staking data for each respective staker
     * @param pRewardsDebt An array of PoolStaker structs containing the staking data for each respective staker
     * @param pRewardsLocked An array of PoolStaker structs containing the staking data for each respective staker
     *
     * Requirements:
     * - The length of all arrays must be equal
     * - The function can only be called by the contract owner
     *
     * Effects:
     * - Updates the staking information for each staker in the pool based on the provided data
     */
    function poolStakersImport(
        address[] calldata pStakersAddress,
        uint256[] calldata pAmount,
        uint256[] calldata pStakedTime,
        uint256[] calldata pRewardsHarvested,
        uint256[] calldata pRewardsDebt,
        uint256[] calldata pRewardsLocked
    ) external onlyOwner {
        require(isMainNetwork, "This is not the main network");
        require(
            pStakersAddress.length == pAmount.length &&
                pStakersAddress.length == pStakedTime.length &&
                pStakersAddress.length == pRewardsHarvested.length &&
                pStakersAddress.length == pRewardsDebt.length &&
                pStakersAddress.length == pRewardsLocked.length,
            "Length mismatch"
        );

        uint256 size = pStakersAddress.length;
        for (uint256 i = 0; i < size; i++) {
            require(!imported[pStakersAddress[i]], "Staker already imported");

            PoolStaker storage staker = poolStakers[pStakersAddress[i]];
            staker.stakerAmount += pAmount[i];
            if (pStakedTime[i] > staker.stakerStakedTime) staker.stakerStakedTime = pStakedTime[i];
            staker.stakerRewardsHarvested += pRewardsHarvested[i];
            staker.stakerRewardsDebt += pRewardsDebt[i];
            staker.stakerRewardsLocked += pRewardsLocked[i];
            imported[pStakersAddress[i]] = true;

            tokensStakedByNetwork += pAmount[i];
        }

        isImportDone = true;
    }
}
Ownable.sol 100 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}
SafeERC20.sol 199 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC-20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    /**
     * @dev An operation with an ERC-20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}
Pausable.sol 119 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.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 Pausable is Context {
    bool private _paused;

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

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _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 {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @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());
    }
}
ReentrancyGuard.sol 87 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @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 EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

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

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
IERC1363.sol 86 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}
Address.sol 150 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert Errors.FailedCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            assembly ("memory-safe") {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert Errors.FailedCall();
        }
    }
}
IERC20.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";
IERC165.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";
Errors.sol 34 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

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

Read Contract

admin 0xf851a440 → address
claimLockDays 0xf3cd8e81 → uint256
claimStartTime 0xa6a11bb1 → uint256
getAddressStakersPresale 0x42dfcb5e → address
getRewards 0x79ee54f7 → uint256
getTokensStakedDetails 0x5e5b077d → uint256[7]
imported 0xc95c16af → bool
isImportDone 0x25ea750f → bool
isMainNetwork 0x285c9dd5 → bool
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
poolAccumulatedRewardsPerShare 0x6e573eba → uint256
poolLastDayReward 0x4f15bba7 → uint256
poolStakers 0xcddb3e7b → uint256, uint256, uint256, uint256, uint256, bool
presaleContract 0x63d9df85 → address
saleToken 0xe985e367 → address
saleTokenTotalMinted 0x18eac306 → uint256
stakeEndTime 0xfafcca8c → uint256
stakeRewardsTokensPerDay 0xe50374df → uint256
stakeStartTime 0x7419f190 → uint256
tokensStakedByNetwork 0xdcfd7ad2 → uint256
tokensStakedByPresale 0x8a6876ad → uint256
tokensStakedTotal 0xb614f4a2 → uint256
tokensStakedTotalLastUpdateTime 0xd0fcb8f8 → uint256

Write Contract 28 functions

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

deposit 0x47e7ef24
address pUserAddress
uint256 pAmount
depositByPresale 0x91c61966
address pUserAddress
uint256 pAmount
harvestRewards 0x2be11ae2
No parameters
pause 0x8456cb59
No parameters
poolStakersImport 0xb78d9396
address[] pStakersAddress
uint256[] pAmount
uint256[] pStakedTime
uint256[] pRewardsHarvested
uint256[] pRewardsDebt
uint256[] pRewardsLocked
renounceOwnership 0x715018a6
No parameters
setAdmin 0x704b6c02
address pAdmin
setClaimLockDays 0xb2819be8
uint256 pClaimLockDays
setClaimStartTime 0x2533a5f6
uint256 pClaimStartTime
setImported 0xbe76f986
address[] pAddresses
bool[] pValues
setIsImportDone 0x33aac1d4
bool pIsImportDone
setIsMainNetwork 0x0188a4fd
bool pIsMainNetwork
setPoolAccumulatedRewardsPerShare 0x0828d2f8
uint256 pPoolAccumulatedRewardsPerShare
setPoolLastDayReward 0xb73d0d0a
uint256 pPoolLastDayReward
setPresaleContract 0xa9bbd114
address pPresaleContract
setSaleToken 0xa29f481c
address pSaleToken
setSaleTokenTotalMinted 0x43405b18
uint256 pSaleTokenTotalMinted
setStakeEndTime 0x747cfc3a
uint256 pStakeEndTime
setStakeRewardsTokensPerDay 0xc8b3e887
uint256 pStakeRewardsTokensPerDay
setStakeStartTime 0xcc1b63d5
uint256 pStakeStartTime
setTokensStakedTotal 0xbd58d6fa
uint256 pAmount
uint256 pUpdateTime
setTokensStakedTotal 0xdf7b633c
uint256 pAmount
setTokensStakedTotalLastUpdateTime 0x31165a7d
uint256 pUpdateTime
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
usersBlacklistAdd 0x8bd8b014
address[] pUsersList
usersBlacklistRemove 0xa54cd6db
address[] pUsersList
withdraw 0x3ccfd60b
No parameters

Recent Transactions

No transactions found for this address