Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x9681382006b59018269E9b802D4a05b8FffA2025
Balance 0.035462 ETH
Nonce 1
Code Size 10454 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

10454 bytes
0x6080604052600436106101ff575f3560e01c8063845ddcb211610113578063ab11417f1161009d578063d5c664c51161006d578063d5c664c514610647578063db2e21bc1461065a578063ef1421871461066e578063f14210a614610682578063f2fde38b146106a1575f80fd5b8063ab11417f146105cb578063b6337a75146105e0578063b6398927146105f5578063c00c635914610614575f80fd5b80639aadeb91116100e35780639aadeb91146105305780639f4157fc14610545578063a57ffde21461055a578063a8602fea14610579578063a98ad46c14610598575f80fd5b8063845ddcb21461047a5780638da5cb5b146104d0578063927c28a2146104f257806394b9cbb214610511575f80fd5b806348f50a8811610194578063701883d711610164578063701883d71461040957806370f6a30314610428578063715018a61461043d578063813d6c9a146104515780638456cb5914610466575f80fd5b806348f50a88146103a957806358faaccc146103be5780635bf5d54c146103dd5780635c975abb146103f2575f80fd5b80633ea521ef116101cf5780633ea521ef146103165780633f4ba83a14610335578063425adae7146103495780634626402b14610372575f80fd5b8063049ac78714610269578063186ba7f114610291578063340ad049146102e257806338c67b73146102f7575f80fd5b366102655761020c6106c0565b600354600454106102385760405162461bcd60e51b815260040161022f906125f6565b60405180910390fd5b5f34116102575760405162461bcd60e51b815260040161022f9061261d565b610263335f8034610708565b005b5f80fd5b348015610274575f80fd5b5061027e600b5481565b6040519081526020015b60405180910390f35b34801561029c575f80fd5b506102a5610d66565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c0830152151560e082015261010001610288565b3480156102ed575f80fd5b5061027e600d5481565b348015610302575f80fd5b50610263610311366004612645565b610e04565b348015610321575f80fd5b50610263610330366004612645565b610e69565b348015610340575f80fd5b5061026361101f565b348015610354575f80fd5b50600c546103629060ff1681565b6040519015158152602001610288565b34801561037d575f80fd5b50600254610391906001600160a01b031681565b6040516001600160a01b039091168152602001610288565b3480156103b4575f80fd5b5061027e600a5481565b3480156103c9575f80fd5b506102636103d836600461265c565b61102f565b3480156103e8575f80fd5b5061027e60045481565b3480156103fd575f80fd5b5060015460ff16610362565b348015610414575f80fd5b5061026361042336600461267c565b61112d565b348015610433575f80fd5b5061027e60085481565b348015610448575f80fd5b50610263611214565b34801561045c575f80fd5b5061027e600e5481565b348015610471575f80fd5b50610263611225565b348015610485575f80fd5b50610499610494366004612645565b611235565b604080519788526020880196909652948601939093526060850191909152608084015260a0830152151560c082015260e001610288565b3480156104db575f80fd5b5060015461010090046001600160a01b0316610391565b3480156104fd575f80fd5b5061026361050c36600461265c565b611285565b34801561051c575f80fd5b5061026361052b366004612645565b611324565b34801561053b575f80fd5b5061027e60075481565b348015610550575f80fd5b5061027e60095481565b348015610565575f80fd5b5061026361057436600461265c565b611520565b348015610584575f80fd5b506102636105933660046126b9565b611610565b3480156105a3575f80fd5b506103917f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec781565b3480156105d6575f80fd5b5061027e60065481565b3480156105eb575f80fd5b5061027e60055481565b348015610600575f80fd5b5061026361060f3660046126db565b6116a9565b34801561061f575f80fd5b506103917f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b281565b6102636106553660046126b9565b611917565b348015610665575f80fd5b50610263611981565b348015610679575f80fd5b50610263611dd3565b34801561068d575f80fd5b5061026361069c366004612645565b611def565b3480156106ac575f80fd5b506102636106bb3660046126b9565b611f05565b60015460ff16156107065760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161022f565b565b5f60036004548154811061071e5761071e612709565b905f5260205f20906007020190505f82116107895760405162461bcd60e51b815260206004820152602560248201527f5061796d656e7420616d6f756e74206d75737420626520677265617465722074604482015264068616e20360dc1b606482015260840161022f565b5f8084600181111561079d5761079d61271d565b03610822575f8260010154116107e95760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642045544820707269636560781b604482015260640161022f565b600182015461080a9061080485670de0b6b3a7640000611f3f565b90611f53565b600a5490915061081a9082611f5e565b600a5561094a565b5f82600201541161086a5760405162461bcd60e51b8152602060048201526012602482015271496e76616c6964205553445420707269636560701b604482015260640161022f565b60028201546108859061080485670de0b6b3a7640000611f3f565b600b549091506108959082611f5e565b600b556040516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018590527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec716906323b872dd906064016020604051808303815f875af115801561090a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092e9190612731565b61094a5760405162461bcd60e51b815260040161022f90612750565b5f81116109aa5760405162461bcd60e51b815260206004820152602860248201527f45434d20616d6f756e7420746f20627579206d75737420626520677265617465604482015267072207468616e20360c41b606482015260840161022f565b815460058301546109bb9083611f5e565b1115610a005760405162461bcd60e51b8152602060048201526014602482015273115e18d959591cc81cdd1859d9481d185c99d95d60621b604482015260640161022f565b6001600160a01b03851615801590610a2a5750856001600160a01b0316856001600160a01b031614155b15610a3b57610a3b85848387611f69565b6005820154610a4a9082611f5e565b60058084019190915554610a5e9082611f5e565b600555600d548110801590610a7457505f600e54115b8015610a825750600c5460ff165b15610b01575f610aa26064610804600e5485611f3f90919063ffffffff16565b9050610aae8282611f5e565b600654909250610abe9082611f5e565b6006556040518181526001600160a01b038816907fda90a0135450a9a3ecdf104f0c192100be3ae5a4216620ded5f6d47596a2c94f9060200160405180910390a2505b6040516370a0823160e01b815230600482015281907f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b26001600160a01b0316906370a0823190602401602060405180830381865afa158015610b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b89919061277e565b1015610be35760405162461bcd60e51b8152602060048201526024808201527f496e73756666696369656e742045434d2062616c616e636520696e20636f6e746044820152631c9858dd60e21b606482015260840161022f565b60405163a9059cbb60e01b81526001600160a01b038781166004830152602482018390527f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b2169063a9059cbb906044016020604051808303815f875af1158015610c4f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c739190612731565b610cb55760405162461bcd60e51b81526020600482015260136024820152721150d3481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161022f565b856001600160a01b03167f320b723126fd88d4912c4bc5090583a7c4a8fbfe8d4ab0a3da4fc25e8de401ed826004548787604051610cf694939291906127b5565b60405180910390a28154600583015410610d5e5760068201805460ff191660011790556004546040517fff2322ca5cc0de99e86dcca47216acc9431131b0653f58418006395c7d33fc3e91610d4e9190815260200190565b60405180910390a1610d5e6123b1565b505050505050565b5f805f805f805f8060038054905060045410610d945760405162461bcd60e51b815260040161022f906125f6565b5f600360045481548110610daa57610daa612709565b905f5260205f2090600702019050600454815f015482600101548360020154846003015485600401548660050154876006015f9054906101000a900460ff1698509850985098509850985098509850509091929394959697565b610e0c61243d565b6003548110610e2d5760405162461bcd60e51b815260040161022f906127df565b60048190556040518181527fbd102993c090f400138a05c1b5b0c9eadb8d94399c432f6522fab9cf26bd180b906020015b60405180910390a150565b610e7161243d565b5f81118015610f0557506040516370a0823160e01b81523060048201527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa158015610edd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f01919061277e565b8111155b610f215760405162461bcd60e51b815260040161022f9061261d565b60025460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec79091169063a9059cbb906044016020604051808303815f875af1158015610f92573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb69190612731565b610fd25760405162461bcd60e51b815260040161022f90612750565b6002546040516001600160a01b03909116907f51a773011f6e17528c0cbc00c115de286c7566ddce4cd97a84b7f08d82dddd839061101490849060019061280c565b60405180910390a250565b61102761243d565b610706612470565b61103761243d565b60035482106110585760405162461bcd60e51b815260040161022f906127df565b6003828154811061106b5761106b612709565b905f5260205f2090600702015f01548111156110c95760405162461bcd60e51b815260206004820181905260248201527f536f6c6420616d6f756e74206578636565647320737461676520746172676574604482015260640161022f565b80600383815481106110dd576110dd612709565b905f5260205f209060070201600501819055507f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d98260405161112191815260200190565b60405180910390a15050565b61113561243d565b60035483106111565760405162461bcd60e51b815260040161022f906127df565b5f8211801561116457505f81115b6111a15760405162461bcd60e51b815260206004820152600e60248201526d496e76616c69642070726963657360901b604482015260640161022f565b5f600384815481106111b5576111b5612709565b905f5260205f20906007020190508281600101819055508181600201819055507f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d98460405161120691815260200190565b60405180910390a150505050565b61121c61243d565b6107065f6124c2565b61122d61243d565b61070661251b565b60038181548110611244575f80fd5b5f9182526020909120600790910201805460018201546002830154600384015460048501546005860154600690960154949650929491939092919060ff1687565b61128d61243d565b5f82116112d55760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a59081b5a5b9a5b5d5b48185b5bdd5b9d60521b604482015260640161022f565b5f81116113195760405162461bcd60e51b8152602060048201526012602482015271496e76616c69642070657263656e7461676560701b604482015260640161022f565b600d91909155600e55565b61132c61243d565b5f811180156113c057506040516370a0823160e01b81523060048201527f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b26001600160a01b0316906370a0823190602401602060405180830381865afa158015611398573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113bc919061277e565b8111155b6113dc5760405162461bcd60e51b815260040161022f9061261d565b7f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b26001600160a01b031663a9059cbb6114236001546001600160a01b036101009091041690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af115801561146d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114919190612731565b6114d55760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b604482015260640161022f565b60015461010090046001600160a01b03166001600160a01b03167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161101491815260200190565b61152861243d565b60035482106115495760405162461bcd60e51b815260040161022f906127df565b6003828154811061155c5761155c612709565b905f5260205f2090600702016005015481116115ba5760405162461bcd60e51b815260206004820152601860248201527f5461726765742062656c6f7720736f6c6420616d6f756e740000000000000000604482015260640161022f565b80600383815481106115ce576115ce612709565b5f9182526020909120600790910201556040517f34cf54504fd39ab670a54acbb37f686c5bd25e6eedfa39889cba899d360bc7d9906111219084815260200190565b61161861243d565b6001600160a01b0381166116605760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161022f565b600280546001600160a01b0319166001600160a01b0383169081179091556040517f97c79b3848e51f57983ac89e4403452655c8d83ceba8199011de63a74f60d1a7905f90a250565b6116b16106c0565b6116b9612556565b600354600454106116dc5760405162461bcd60e51b815260040161022f906125f6565b5f82116116fb5760405162461bcd60e51b815260040161022f9061261d565b4660011461174b5760405162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920457468657265756d206d61696e6e657420737570706f7274656400604482015260640161022f565b6040516370a0823160e01b815233600482015282907f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa1580156117af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117d3919061277e565b10156118215760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e7420555344542062616c616e636500000000000000604482015260640161022f565b604051636eb1769f60e11b815233600482015230602482015282907f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b03169063dd62ed3e90604401602060405180830381865afa15801561188b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118af919061277e565b10156118fd5760405162461bcd60e51b815260206004820152601b60248201527f496e73756666696369656e74205553445420616c6c6f77616e63650000000000604482015260640161022f565b61190a3382600185610708565b61191360015f55565b5050565b61191f6106c0565b611927612556565b6003546004541061194a5760405162461bcd60e51b815260040161022f906125f6565b5f34116119695760405162461bcd60e51b815260040161022f9061261d565b61197533825f34610708565b61197e60015f55565b50565b611989612556565b61199161243d565b60015460ff166119e35760405162461bcd60e51b815260206004820152601760248201527f436f6e7472616374206d75737420626520706175736564000000000000000000604482015260640161022f565b6002546001600160a01b0316611a2e5760405162461bcd60e51b815260206004820152601060248201526f151c99585cdd5c9e481b9bdd081cd95d60821b604482015260640161022f565b6040516370a0823160e01b815230600482015247905f907f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa158015611a94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab8919061277e565b6040516370a0823160e01b81523060048201529091505f906001600160a01b037f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b216906370a0823190602401602060405180830381865afa158015611b1f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b43919061277e565b90508215611be3576002546040515f916001600160a01b03169085908381818185875af1925050503d805f8114611b95576040519150601f19603f3d011682016040523d82523d5f602084013e611b9a565b606091505b5050905080611be15760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161022f565b505b8115611c9a5760025460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018490527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec79091169063a9059cbb906044016020604051808303815f875af1158015611c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c7e9190612731565b611c9a5760405162461bcd60e51b815260040161022f90612750565b8015611d775760025460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390527f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b29091169063a9059cbb906044016020604051808303815f875af1158015611d11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d359190612731565b611d775760405162461bcd60e51b81526020600482015260136024820152721150d3481d1c985b9cd9995c8819985a5b1959606a1b604482015260640161022f565b60025460408051858152602081018590529081018390526001600160a01b03909116907f2369db1bafee945aee5630782f4a170682e3f8188d8dc247a4c73eb8c9e692d29060600160405180910390a250505061070660015f55565b611ddb61243d565b600c805460ff19811660ff90911615179055565b611df761243d565b5f81118015611e065750478111155b611e225760405162461bcd60e51b815260040161022f9061261d565b6002546040515f916001600160a01b03169083908381818185875af1925050503d805f8114611e6c576040519150601f19603f3d011682016040523d82523d5f602084013e611e71565b606091505b5050905080611eb85760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161022f565b6002546040516001600160a01b03909116907f51a773011f6e17528c0cbc00c115de286c7566ddce4cd97a84b7f08d82dddd8390611ef99085905f9061280c565b60405180910390a25050565b611f0d61243d565b6001600160a01b038116611f3657604051631e4fbdf760e01b81525f600482015260240161022f565b61197e816124c2565b5f611f4a8284612834565b90505b92915050565b5f611f4a828461284b565b5f611f4a828461286a565b5f600360045481548110611f7f57611f7f612709565b905f5260205f20906007020190505f611faa6064610804846004015488611f3f90919063ffffffff16565b9050801561216d576001836001811115611fc657611fc661271d565b036120bc5760405163a9059cbb60e01b81526001600160a01b038781166004830152602482018390527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7169063a9059cbb906044016020604051808303815f875af1158015612037573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205b9190612731565b6120a75760405162461bcd60e51b815260206004820152601d60248201527f5553445420726566657272616c207472616e73666572206661696c6564000000604482015260640161022f565b6009546120b49082611f5e565b60095561216d565b5f866001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612105576040519150601f19603f3d011682016040523d82523d5f602084013e61210a565b606091505b505090508061215b5760405162461bcd60e51b815260206004820152601c60248201527f45544820726566657272616c207472616e73666572206661696c656400000000604482015260640161022f565b6008546121689083611f5e565b600855505b5f61218a6064610804856003015488611f3f90919063ffffffff16565b90508015612363576040516370a0823160e01b815230600482015281907f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b26001600160a01b0316906370a0823190602401602060405180830381865afa1580156121f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061221a919061277e565b10156122765760405162461bcd60e51b815260206004820152602560248201527f496e73756666696369656e742045434d2062616c616e636520666f7220726566604482015264195c9c985b60da1b606482015260840161022f565b60405163a9059cbb60e01b81526001600160a01b038881166004830152602482018390527f0000000000000000000000006f9c25edc02f21e9df8050a3e67947c99b88f0b2169063a9059cbb906044016020604051808303815f875af11580156122e2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123069190612731565b6123525760405162461bcd60e51b815260206004820152601c60248201527f45434d20726566657272616c207472616e73666572206661696c656400000000604482015260640161022f565b60075461235f9082611f5e565b6007555b866001600160a01b03167f6b559d3769fcb93d360ec386cf9777c3a2c72fed603bd24ae7431917c4b417008284876040516123a09392919061287d565b60405180910390a250505050505050565b5f60045460016123c1919061286a565b90505b600354811015612434575f600382815481106123e2576123e2612709565b905f5260205f2090600702015f0154111561242c5760048190556040518181527fbd102993c090f400138a05c1b5b0c9eadb8d94399c432f6522fab9cf26bd180b90602001610e5e565b6001016123c4565b50600354600455565b6001546001600160a01b036101009091041633146107065760405163118cdaa760e01b815233600482015260240161022f565b6124786125ad565b6001805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600180546001600160a01b03838116610100818102610100600160a81b031985161790945560405193909204169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6125236106c0565b6001805460ff1916811790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258336124a5565b60025f54036125a75760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161022f565b60025f55565b60015460ff166107065760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161022f565b6020808252600d908201526c1250d3c81a185cc8195b991959609a1b604082015260600190565b6020808252600e908201526d125b9d985b1a5908185b5bdd5b9d60921b604082015260600190565b5f60208284031215612655575f80fd5b5035919050565b5f806040838503121561266d575f80fd5b50508035926020909101359150565b5f805f6060848603121561268e575f80fd5b505081359360208301359350604090920135919050565b6001600160a01b038116811461197e575f80fd5b5f602082840312156126c9575f80fd5b81356126d4816126a5565b9392505050565b5f80604083850312156126ec575f80fd5b8235915060208301356126fe816126a5565b809150509250929050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215612741575f80fd5b815180151581146126d4575f80fd5b6020808252601490820152731554d115081d1c985b9cd9995c8819985a5b195960621b604082015260600190565b5f6020828403121561278e575f80fd5b5051919050565b600281106127b157634e487b7160e01b5f52602160045260245ffd5b9052565b84815260208101849052608081016127d06040830185612795565b82606083015295945050505050565b602080825260139082015272092dcecc2d8d2c840e6e8c2ceca40d2dcc8caf606b1b604082015260600190565b828152604081016126d46020830184612795565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417611f4d57611f4d612820565b5f8261286557634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115611f4d57611f4d612820565b83815260208101839052606081016128986040830184612795565b94935050505056fea2646970667358221220d2e3ff2357bd2c8bd6d9de3ba2bb85a711f1d04038415a5bdf7df2cb227dfe0764736f6c634300081a0033

Verified Source Code Partial Match

Compiler: v0.8.26+commit.8a97fa7a EVM: cancun Optimization: Yes (200 runs)
ECMCoinICO.sol 950 lines
// SPDX-License-Identifier: MIT
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol


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

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


// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

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

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

// File: @openzeppelin/contracts/utils/Context.sol


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

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


// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;


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

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


// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;


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

// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: contracts/ECMCoinICO.sol


pragma solidity ^0.8.26;






/// @title ECM Coin ICO Contract
/// @notice Manages ICO stages, purchases, referrals, and bonuses for ECM token
contract ECMCoinICO is ReentrancyGuard, Pausable, Ownable(msg.sender) {
    using SafeMath for uint256;

    // Core token contracts
    IERC20 public immutable ecmCoin;    // ECM Coin contract
    IERC20 public immutable usdtToken;   // USDT token contract
    address payable public treasuryWallet;

    enum PaymentType { ETH, USDT }

    // Stage structure for ICO phases
    struct Stage {
        uint256 target;           // Total tokens to sell in this stage
        uint256 ethPrice;         // Price in ETH
        uint256 usdtPrice;        // Price in USDT
        uint256 ecmRefBonus;      // Referral bonus in ECM (%)
        uint256 paymentRefBonus;  // Referral bonus in payment token (%)
        uint256 ecmSold;          // Amount sold in this stage
        bool isCompleted;         // Stage completion status
    }

    Stage[] public stages;

    // State variables
    uint256 public currentStage;
    uint256 public totalEcmSold;
    uint256 public totalBonusDistributed;
    uint256 public totalECMReferralDistributed;
    uint256 public totalETHReferralDistributed;
    uint256 public totalUSDTReferralDistributed;
    uint256 public totalEcmSoldByETH;
    uint256 public totalEcmSoldByUSDT;

    bool public isBonusEnabled = false;  // Default enabled for bonus distribution
    uint256 public minBonusAmount = 300 * 1e18;  // Minimum amount for bonus eligibility
    uint256 public bonusPercentage = 5;         // Bonus percentage

    // Events
    event ECMPurchased(address indexed buyer, uint256 amount, uint256 stage, PaymentType paymentType, uint256 paymentAmount);
    event ReferralRewardPaid(address indexed referrer, uint256 ecmAmount, uint256 paymentAmount, PaymentType paymentType);
    event BonusTokensAwarded(address indexed buyer, uint256 bonusAmount);
    event TreasuryWalletUpdated(address indexed newWallet);
    event TokensWithdrawn(address indexed to, uint256 amount);
    event FundsWithdrawn(address indexed to, uint256 amount, PaymentType paymentType);
    event EmergencyWithdraw(address indexed treasury, uint256 ethAmount, uint256 usdtAmount, uint256 ecmAmount);
    event StageCompleted(uint256 stageIndex);
    event StageUpdated(uint256 stageIndex);
    event CurrentStageUpdated(uint256 newStage);

    /// @notice Initialize contract with token addresses
    constructor(address _ecmCoin, address _usdtToken) {
        require(_ecmCoin != address(0) && _usdtToken != address(0), "Invalid addresses");
        ecmCoin = IERC20(_ecmCoin);
        usdtToken = IERC20(_usdtToken);
        treasuryWallet = payable(owner());
        
        // Initialize ICO stages
        stages.push(Stage(200000 * 1e18, 0.00040 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(200000 * 1e18, 0.00046 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(200000 * 1e18, 0.00047 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(100000 * 1e18, 0.00048 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(100000 * 1e18, 0.00049 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(50000 * 1e18, 0.00050 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(50000 * 1e18, 0.00051 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(50000 * 1e18, 0.00052 ether, 1.20 * 1e6, 2, 3, 0, false));
        stages.push(Stage(50000 * 1e18, 0.00053 ether, 1.20 * 1e6, 2, 3, 0, false));
    }

    /// @notice Handle direct ETH transfers
    receive() external payable whenNotPaused {
        require(currentStage < stages.length, "ICO has ended");
        require(msg.value > 0, "Invalid amount");
        _buyECM(msg.sender, address(0), PaymentType.ETH, msg.value);
    }

    /// @notice Buy ECM with ETH using referral
    function buyECMWithETH(address referrer) external payable whenNotPaused nonReentrant {
        require(currentStage < stages.length, "ICO has ended");
        require(msg.value > 0, "Invalid amount");
        _buyECM(msg.sender, referrer, PaymentType.ETH, msg.value);
    }

    /// @notice Buy ECM with USDT using referral
    function buyECMWithUSDT(uint256 amount, address referrer) external whenNotPaused nonReentrant {
        require(currentStage < stages.length, "ICO has ended");
        require(amount > 0, "Invalid amount");
        require(block.chainid == 1, "Only Ethereum mainnet supported");
        require(usdtToken.balanceOf(msg.sender) >= amount, "Insufficient USDT balance");
        require(usdtToken.allowance(msg.sender, address(this)) >= amount, "Insufficient USDT allowance");
        _buyECM(msg.sender, referrer, PaymentType.USDT, amount);
    }

    /// @notice Internal function to handle ECM purchases
    function _buyECM(address buyer, address referrer, PaymentType paymentType, uint256 paymentAmount) internal {
        Stage storage stage = stages[currentStage];
        require(paymentAmount > 0, "Payment amount must be greater than 0");

        uint256 ecmToBuy;
        if (paymentType == PaymentType.ETH) {
            require(stage.ethPrice > 0, "Invalid ETH price");
            ecmToBuy = paymentAmount.mul(1e18).div(stage.ethPrice);
            totalEcmSoldByETH = totalEcmSoldByETH.add(ecmToBuy);
        } else {
            require(stage.usdtPrice > 0, "Invalid USDT price"); 
            ecmToBuy = paymentAmount.mul(1e18).div(stage.usdtPrice);
            totalEcmSoldByUSDT = totalEcmSoldByUSDT.add(ecmToBuy);
            require(usdtToken.transferFrom(buyer, address(this), paymentAmount), "USDT transfer failed");
        }

        require(ecmToBuy > 0, "ECM amount to buy must be greater than 0");
        require(stage.ecmSold.add(ecmToBuy) <= stage.target, "Exceeds stage target");

        if (referrer != address(0) && referrer != buyer) {
            _handleReferral(referrer, paymentAmount, ecmToBuy, paymentType);
        }

        // Update state and handle bonus
        stage.ecmSold = stage.ecmSold.add(ecmToBuy);
        totalEcmSold = totalEcmSold.add(ecmToBuy);

        if (ecmToBuy >= minBonusAmount && bonusPercentage > 0 && isBonusEnabled) {
            uint256 bonusTokens = ecmToBuy.mul(bonusPercentage).div(100);
            ecmToBuy = ecmToBuy.add(bonusTokens);
            totalBonusDistributed = totalBonusDistributed.add(bonusTokens);
            emit BonusTokensAwarded(buyer, bonusTokens);
        }

        require(ecmCoin.balanceOf(address(this)) >= ecmToBuy, "Insufficient ECM balance in contract");
        require(ecmCoin.transfer(buyer, ecmToBuy), "ECM transfer failed");

        emit ECMPurchased(buyer, ecmToBuy, currentStage, paymentType, paymentAmount);

        if (stage.ecmSold >= stage.target) {
            stage.isCompleted = true;
            emit StageCompleted(currentStage);
            progressToNextStage();
        }
    }

    /// @notice Handle referral rewards
    function _handleReferral(address referrer, uint256 paymentAmount, uint256 ecmAmount, PaymentType paymentType) internal {
        Stage storage stage = stages[currentStage];

        uint256 paymentReferralAmount = paymentAmount.mul(stage.paymentRefBonus).div(100);
        if (paymentReferralAmount > 0) {
            if (paymentType == PaymentType.USDT) {
                require(usdtToken.transfer(referrer, paymentReferralAmount), "USDT referral transfer failed");
                totalUSDTReferralDistributed = totalUSDTReferralDistributed.add(paymentReferralAmount);
            } else {
                (bool success, ) = payable(referrer).call{value: paymentReferralAmount}("");
                require(success, "ETH referral transfer failed");
                totalETHReferralDistributed = totalETHReferralDistributed.add(paymentReferralAmount);
            }
        }

        uint256 ecmReferralAmount = ecmAmount.mul(stage.ecmRefBonus).div(100);
        if (ecmReferralAmount > 0) {
            require(ecmCoin.balanceOf(address(this)) >= ecmReferralAmount, "Insufficient ECM balance for referral");
            require(ecmCoin.transfer(referrer, ecmReferralAmount), "ECM referral transfer failed");
            totalECMReferralDistributed = totalECMReferralDistributed.add(ecmReferralAmount);
        }

        emit ReferralRewardPaid(referrer, ecmReferralAmount, paymentReferralAmount, paymentType);
    }

    // Admin Functions

    /// @notice Toggle bonus token distribution on/off
    /// @dev Only owner can call this function
    function toggleBonus() external onlyOwner {
        isBonusEnabled = !isBonusEnabled;
    }

    /// @notice Set bonus parameters
    function setBonusParameters(uint256 _minAmount, uint256 _percentage) external onlyOwner {
        require(_minAmount > 0, "Invalid minimum amount");
        require(_percentage > 0, "Invalid percentage");
        minBonusAmount = _minAmount;
        bonusPercentage = _percentage;
    }

    /// @notice Progress to next available stage
    function progressToNextStage() internal {
        for (uint256 i = currentStage + 1; i < stages.length; i++) {
            if (stages[i].target > 0) {
                currentStage = i;
                emit CurrentStageUpdated(i);
                return;
            }
        }
        currentStage = stages.length;
    }

    /// @notice Admin control to set current stage
    function setCurrentStage(uint256 newStage) external onlyOwner {
        require(newStage < stages.length, "Invalid stage index");
        currentStage = newStage;
        emit CurrentStageUpdated(newStage);
    }

    /// @notice Get current stage information
    function currentStageInfo() external view returns (
        uint256 stageIndex,
        uint256 target,
        uint256 ethPrice,
        uint256 usdtPrice,
        uint256 ecmRefBonus,
        uint256 paymentRefBonus,
        uint256 ecmSold,
        bool isCompleted
    ) {
        require(currentStage < stages.length, "ICO has ended");
        Stage storage stage = stages[currentStage];
        return (
            currentStage,
            stage.target,
            stage.ethPrice,
            stage.usdtPrice,
            stage.ecmRefBonus,
            stage.paymentRefBonus,
            stage.ecmSold,
            stage.isCompleted
        );
    }

    /// @notice Update stage target
    function updateStageTarget(uint256 stageIndex, uint256 target) external onlyOwner {
        require(stageIndex < stages.length, "Invalid stage index");
        require(target > stages[stageIndex].ecmSold, "Target below sold amount");
        stages[stageIndex].target = target;
        emit StageUpdated(stageIndex);
    }

    /// @notice Update stage ecm sold
    function updateStageSold(uint256 stageIndex, uint256 soldAmount) external onlyOwner {
        require(stageIndex < stages.length, "Invalid stage index");
        require(soldAmount <= stages[stageIndex].target, "Sold amount exceeds stage target");
        stages[stageIndex].ecmSold = soldAmount;
        emit StageUpdated(stageIndex);
    }

    /// @notice Update stage prices
    function updateStagePrices(uint256 stageIndex, uint256 ethPrice, uint256 usdtPrice) external onlyOwner {
        require(stageIndex < stages.length, "Invalid stage index");
        require(ethPrice > 0 && usdtPrice > 0, "Invalid prices");
        Stage storage stage = stages[stageIndex];
        stage.ethPrice = ethPrice;
        stage.usdtPrice = usdtPrice;
        emit StageUpdated(stageIndex);
    }

    // Withdrawal Functions

    /// @notice Withdraw ECM tokens
    function withdrawECM(uint256 amount) external onlyOwner {
        require(amount > 0 && amount <= ecmCoin.balanceOf(address(this)), "Invalid amount");
        require(ecmCoin.transfer(owner(), amount), "Token transfer failed");
        emit TokensWithdrawn(owner(), amount);
    }

    /// @notice Withdraw ETH
    function withdrawETH(uint256 amount) external onlyOwner {
        require(amount > 0 && amount <= address(this).balance, "Invalid amount");
        (bool success, ) = treasuryWallet.call{value: amount}("");
        require(success, "ETH transfer failed");
        emit FundsWithdrawn(treasuryWallet, amount, PaymentType.ETH);
    }

    /// @notice Withdraw USDT
    function withdrawUSDT(uint256 amount) external onlyOwner {
       require(amount > 0 && amount <= usdtToken.balanceOf(address(this)), "Invalid amount");
       require(usdtToken.transfer(treasuryWallet, amount), "USDT transfer failed");
       emit FundsWithdrawn(treasuryWallet, amount, PaymentType.USDT);
    }

    /// @notice Emergency withdrawal of all funds
    function emergencyWithdraw() external nonReentrant onlyOwner {
        require(paused(), "Contract must be paused");
        require(treasuryWallet != address(0), "Treasury not set");

        uint256 ethBalance = address(this).balance;
        uint256 usdtBalance = usdtToken.balanceOf(address(this));
        uint256 ecmBalance = ecmCoin.balanceOf(address(this));
        
        if (ethBalance > 0) {
            (bool success, ) = treasuryWallet.call{value: ethBalance}("");
            require(success, "ETH transfer failed");
        }
        
        if (usdtBalance > 0) {
            require(usdtToken.transfer(treasuryWallet, usdtBalance), "USDT transfer failed");
        }
        
        if (ecmBalance > 0) {
            require(ecmCoin.transfer(treasuryWallet, ecmBalance), "ECM transfer failed");
        }

        emit EmergencyWithdraw(treasuryWallet, ethBalance, usdtBalance, ecmBalance);
    }

    /// @notice Update treasury wallet address
    function setTreasuryWallet(address payable _newWallet) external onlyOwner {
        require(_newWallet != address(0), "Invalid address");
        treasuryWallet = _newWallet;
        emit TreasuryWalletUpdated(_newWallet);
    }

    /// @notice Pause the contract
    function pause() external onlyOwner {
        _pause();
    }

    /// @notice Unpause the contract
    function unpause() external onlyOwner {
        _unpause();
    }
}

Read Contract

bonusPercentage 0x813d6c9a → uint256
currentStage 0x5bf5d54c → uint256
currentStageInfo 0x186ba7f1 → uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool
ecmCoin 0xc00c6359 → address
isBonusEnabled 0x425adae7 → bool
minBonusAmount 0x340ad049 → uint256
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
stages 0x845ddcb2 → uint256, uint256, uint256, uint256, uint256, uint256, bool
totalBonusDistributed 0xab11417f → uint256
totalECMReferralDistributed 0x9aadeb91 → uint256
totalETHReferralDistributed 0x70f6a303 → uint256
totalEcmSold 0xb6337a75 → uint256
totalEcmSoldByETH 0x48f50a88 → uint256
totalEcmSoldByUSDT 0x049ac787 → uint256
totalUSDTReferralDistributed 0x9f4157fc → uint256
treasuryWallet 0x4626402b → address
usdtToken 0xa98ad46c → address

Write Contract 17 functions

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

buyECMWithETH 0xd5c664c5
address referrer
buyECMWithUSDT 0xb6398927
uint256 amount
address referrer
emergencyWithdraw 0xdb2e21bc
No parameters
pause 0x8456cb59
No parameters
renounceOwnership 0x715018a6
No parameters
setBonusParameters 0x927c28a2
uint256 _minAmount
uint256 _percentage
setCurrentStage 0x38c67b73
uint256 newStage
setTreasuryWallet 0xa8602fea
address _newWallet
toggleBonus 0xef142187
No parameters
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
updateStagePrices 0x701883d7
uint256 stageIndex
uint256 ethPrice
uint256 usdtPrice
updateStageSold 0x58faaccc
uint256 stageIndex
uint256 soldAmount
updateStageTarget 0xa57ffde2
uint256 stageIndex
uint256 target
withdrawECM 0x94b9cbb2
uint256 amount
withdrawETH 0xf14210a6
uint256 amount
withdrawUSDT 0x3ea521ef
uint256 amount

Recent Transactions

No transactions found for this address