Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0xe8FCe3F0A9F1cd2E3f737c91043C6Bc5894cbB9b
Balance 0 ETH
Nonce 1
Code Size 12782 bytes
Indexed Transactions 0 (1 on-chain, 1.2% indexed)
External Etherscan · Sourcify

Contract Bytecode

12782 bytes
0x6080604052600436106101b6575f3560e01c8063715018a6116100eb578063aac61a1f11610089578063e9691ade11610063578063e9691ade146105e4578063f16f01161461060c578063f2fde38b14610628578063f3d7185314610650576101b6565b8063aac61a1f14610544578063b4fb3ee314610580578063e0b2b642146105bc576101b6565b806384ba3f69116100c557806384ba3f691461049e5780638da5cb5b146104da578063a26dbf2614610504578063a43be57b1461052e576101b6565b8063715018a614610422578063788ce6f21461043857806382dc4a0514610462576101b6565b80634ebafbc41161015857806354f63ee51161013257806354f63ee51461037c5780635e337fc11461039257806363b20117146103ce57806369bb4dc2146103f8576101b6565b80634ebafbc4146102ee5780634f7375201461032a57806353135ca014610352576101b6565b806335c1d3491161019457806335c1d349146102365780633ad10ef6146102725780633b97e8561461029c578063420dc9b5146102c6576101b6565b806324ffea1a146101ba57806331711884146101e4578063354e7f1c1461020e575b5f80fd5b3480156101c5575f80fd5b506101ce61068c565b6040516101db919061205a565b60405180910390f35b3480156101ef575f80fd5b506101f86106b1565b604051610205919061208b565b60405180910390f35b348015610219575f80fd5b50610234600480360381019061022f919061213e565b6106b7565b005b348015610241575f80fd5b5061025c600480360381019061025791906121a2565b610895565b604051610269919061205a565b60405180910390f35b34801561027d575f80fd5b506102866108d0565b604051610293919061205a565b60405180910390f35b3480156102a7575f80fd5b506102b06108f4565b6040516102bd919061208b565b60405180910390f35b3480156102d1575f80fd5b506102ec60048036038101906102e791906121cd565b6108fa565b005b3480156102f9575f80fd5b50610314600480360381019061030f919061220b565b61095a565b604051610321919061233c565b60405180910390f35b348015610335575f80fd5b50610350600480360381019061034b919061235c565b610b5a565b005b34801561035d575f80fd5b50610366610d23565b60405161037391906123a9565b60405180910390f35b348015610387575f80fd5b50610390610d35565b005b34801561039d575f80fd5b506103b860048036038101906103b391906123c2565b610dad565b6040516103c5919061208b565b60405180910390f35b3480156103d9575f80fd5b506103e2610dc2565b6040516103ef919061208b565b60405180910390f35b348015610403575f80fd5b5061040c610dc8565b604051610419919061208b565b60405180910390f35b34801561042d575f80fd5b50610436610dce565b005b348015610443575f80fd5b5061044c610de1565b604051610459919061205a565b60405180910390f35b34801561046d575f80fd5b50610488600480360381019061048391906123c2565b610e05565b60405161049591906123a9565b60405180910390f35b3480156104a9575f80fd5b506104c460048036038101906104bf91906123c2565b610e22565b6040516104d1919061208b565b60405180910390f35b3480156104e5575f80fd5b506104ee610e37565b6040516104fb919061205a565b60405180910390f35b34801561050f575f80fd5b50610518610e5e565b604051610525919061208b565b60405180910390f35b348015610539575f80fd5b50610542610e64565b005b34801561054f575f80fd5b5061056a6004803603810190610565919061235c565b610edc565b604051610577919061208b565b60405180910390f35b34801561058b575f80fd5b506105a660048036038101906105a191906123c2565b611043565b6040516105b391906123a9565b60405180910390f35b3480156105c7575f80fd5b506105e260048036038101906105dd91906125fd565b611060565b005b3480156105ef575f80fd5b5061060a60048036038101906106059190612685565b611222565b005b6106266004803603810190610621919061235c565b611395565b005b348015610633575f80fd5b5061064e600480360381019061064991906123c2565b611766565b005b34801561065b575f80fd5b506106766004803603810190610671919061235c565b6117ea565b604051610683919061208b565b60405180910390f35b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b6106bf611951565b6106c76119d8565b5f82036106d2575f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610740576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073790612755565b60405180910390fd5b816002819055508360035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060085f6101000a81548160ff0219169083151502179055508373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061080d91906127a9565b60ff16600481905550826005819055507fb9e4d4c8529111d308c22bede75b343376625d7da379634766d264fdf1cd24b78484848460405161085294939291906127d4565b60405180910390a16108873330858773ffffffffffffffffffffffffffffffffffffffff16611a1e909392919063ffffffff16565b61088f611aa0565b50505050565b600981815481106108a4575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f0000000000000000000000007c437c8929f84e18f4a5649498bec66950866b8a81565b60045481565b610902611951565b8060065f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055505050565b606081831061099e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099590612861565b60405180910390fd5b5f600c5483116109ae57826109b2565b600c545b90505f600c5485116109c457846109c8565b600c545b90505f81836109d791906128ac565b67ffffffffffffffff8111156109f0576109ef612401565b5b604051908082528060200260200182016040528015610a2957816020015b610a16611fed565b815260200190600190039081610a0e5790505b5090505f8290505b83811015610b4d57604051806040016040528060098381548110610a5857610a576128df565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600b5f60098581548110610ab257610ab16128df565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054815250828483610b2491906128ac565b81518110610b3557610b346128df565b5b60200260200101819052508080600101915050610a31565b5080935050505092915050565b610b62611951565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610c2d575f47905081811015610bdc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd390612956565b60405180910390fd5b610be4610e37565b73ffffffffffffffffffffffffffffffffffffffff166108fc8390811502906040515f60405180830381858888f19350505050158015610c26573d5f803e3d5ffd5b5050610d1f565b5f8273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c67919061205a565b602060405180830381865afa158015610c82573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca69190612988565b905081811015610ceb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce2906129fd565b60405180910390fd5b610d1d610cf6610e37565b838573ffffffffffffffffffffffffffffffffffffffff16611aa99092919063ffffffff16565b505b5050565b60085f9054906101000a900460ff1681565b610d3d611951565b5f151560085f9054906101000a900460ff16151514610d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8890612a65565b60405180910390fd5b600160085f6101000a81548160ff021916908315150217905550565b600b602052805f5260405f205f915090505481565b600d5481565b60055481565b610dd6611951565b610ddf5f611b28565b565b7f00000000000000000000000008830e4ae1c296d9b88ce6241fe3637acb7bdb6081565b6006602052805f5260405f205f915054906101000a900460ff1681565b6007602052805f5260405f205f915090505481565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600c5481565b610e6c611951565b6001151560085f9054906101000a900460ff16151514610ec1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb890612acd565b60405180910390fd5b5f60085f6101000a81548160ff021916908315150217905550565b5f805f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461100f576001151560065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16151514610fa1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9890612b35565b60405180910390fd5b5f60075f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905080600454600a610ff29190612c82565b85610ffd9190612ccc565b6110079190612d3a565b915050611039565b600254600454600a6110219190612c82565b8461102c9190612ccc565b6110369190612d3a565b90505b8091505092915050565b600a602052805f5260405f205f915054906101000a900460ff1681565b611068611951565b81518351146110ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a390612db4565b60405180910390fd5b5f81146110bb57806002819055505b5f5b83518110156111e1576001151560065f8684815181106110e0576110df6128df565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16151514611139575f80fd5b5f83828151811061114d5761114c6128df565b5b60200260200101510361115e575f80fd5b828181518110611171576111706128df565b5b602002602001015160075f86848151811061118f5761118e6128df565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208190555080806001019150506110bd565b507fe39f11914160041ca57c83bc6b85a442d182048e8fe030ff6dc02603380cf46183838360405161121593929190612f22565b60405180910390a1505050565b61122a611951565b805182511461126e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126590612db4565b60405180910390fd5b5f5b8251811015611390575f82828151811061128d5761128c6128df565b5b60200260200101510361129e575f80fd5b600160065f8584815181106112b6576112b56128df565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508181815181106113205761131f6128df565b5b602002602001015160075f85848151811061133e5761133d6128df565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508080600101915050611270565b505050565b6001151560085f9054906101000a900460ff161515146113ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e190612acd565b60405180910390fd5b6113f26119d8565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361142c573461142e565b815b90505f61143b8483610edc565b90505f810361147f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161147690612fd5565b60405180910390fd5b60055481600d546114909190612ff3565b11156114d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114c890613070565b60405180910390fd5b80600d5f8282546114e29190612ff3565b92505081905550600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1661160657600933908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600a5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055506001600c5f8282546115fe9190612ff3565b925050819055505b80600b5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546116529190612ff3565b925050819055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8daf503382665d950e449b86172be5222275c90f4ddf69c29fdaa8237a562a6d84846040516116b892919061308e565b60405180910390a35f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611702576116fd8484611be9565b61170c565b61170b34611caf565b5b611758338260035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611aa99092919063ffffffff16565b5050611762611aa0565b5050565b61176e611951565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036117de575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016117d5919061205a565b60405180910390fd5b6117e781611b28565b50565b5f805f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461191d576001151560065f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff161515146118af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118a690612b35565b60405180910390fd5b5f60075f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050600454600a6118ff9190612c82565b818561190b9190612ccc565b6119159190612d3a565b915050611947565b600454600a61192c9190612c82565b6002548461193a9190612ccc565b6119449190612d3a565b90505b8091505092915050565b611959611da2565b73ffffffffffffffffffffffffffffffffffffffff16611977610e37565b73ffffffffffffffffffffffffffffffffffffffff16146119d65761199a611da2565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016119cd919061205a565b60405180910390fd5b565b600260015403611a14576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600181905550565b611a9a848573ffffffffffffffffffffffffffffffffffffffff166323b872dd868686604051602401611a53939291906130b5565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611da9565b50505050565b60018081905550565b611b23838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401611adc9291906130ea565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611da9565b505050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f6064600583611bf99190612ccc565b611c039190612d3a565b9050611c52337f0000000000000000000000007c437c8929f84e18f4a5649498bec66950866b8a838673ffffffffffffffffffffffffffffffffffffffff16611a1e909392919063ffffffff16565b611caa337f00000000000000000000000008830e4ae1c296d9b88ce6241fe3637acb7bdb608385611c8391906128ac565b8673ffffffffffffffffffffffffffffffffffffffff16611a1e909392919063ffffffff16565b505050565b5f6064600583611cbf9190612ccc565b611cc99190612d3a565b90507f0000000000000000000000007c437c8929f84e18f4a5649498bec66950866b8a73ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015611d2e573d5f803e3d5ffd5b507f00000000000000000000000008830e4ae1c296d9b88ce6241fe3637acb7bdb6073ffffffffffffffffffffffffffffffffffffffff166108fc8284611d7591906128ac565b90811502906040515f60405180830381858888f19350505050158015611d9d573d5f803e3d5ffd5b505050565b5f33905090565b5f611dd3828473ffffffffffffffffffffffffffffffffffffffff16611e3e90919063ffffffff16565b90505f815114158015611df7575080806020019051810190611df59190613125565b155b15611e3957826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401611e30919061205a565b60405180910390fd5b505050565b6060611e4b83835f611e53565b905092915050565b606081471015611e9a57306040517fcd786059000000000000000000000000000000000000000000000000000000008152600401611e91919061205a565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff168486604051611ec291906131a2565b5f6040518083038185875af1925050503d805f8114611efc576040519150601f19603f3d011682016040523d82523d5f602084013e611f01565b606091505b5091509150611f11868383611f1c565b925050509392505050565b606082611f3157611f2c82611fa9565b611fa1565b5f8251148015611f5757505f8473ffffffffffffffffffffffffffffffffffffffff163b145b15611f9957836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401611f90919061205a565b60405180910390fd5b819050611fa2565b5b9392505050565b5f81511115611fbb5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052805f73ffffffffffffffffffffffffffffffffffffffff1681526020015f81525090565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6120448261201b565b9050919050565b6120548161203a565b82525050565b5f60208201905061206d5f83018461204b565b92915050565b5f819050919050565b61208581612073565b82525050565b5f60208201905061209e5f83018461207c565b92915050565b5f604051905090565b5f80fd5b5f80fd5b6120be8161203a565b81146120c8575f80fd5b50565b5f813590506120d9816120b5565b92915050565b6120e881612073565b81146120f2575f80fd5b50565b5f81359050612103816120df565b92915050565b5f8115159050919050565b61211d81612109565b8114612127575f80fd5b50565b5f8135905061213881612114565b92915050565b5f805f8060808587031215612156576121556120ad565b5b5f612163878288016120cb565b9450506020612174878288016120f5565b9350506040612185878288016120f5565b92505060606121968782880161212a565b91505092959194509250565b5f602082840312156121b7576121b66120ad565b5b5f6121c4848285016120f5565b91505092915050565b5f80604083850312156121e3576121e26120ad565b5b5f6121f0858286016120cb565b92505060206122018582860161212a565b9150509250929050565b5f8060408385031215612221576122206120ad565b5b5f61222e858286016120f5565b925050602061223f858286016120f5565b9150509250929050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b61227b8161203a565b82525050565b61228a81612073565b82525050565b604082015f8201516122a45f850182612272565b5060208201516122b76020850182612281565b50505050565b5f6122c88383612290565b60408301905092915050565b5f602082019050919050565b5f6122ea82612249565b6122f48185612253565b93506122ff83612263565b805f5b8381101561232f57815161231688826122bd565b9750612321836122d4565b925050600181019050612302565b5085935050505092915050565b5f6020820190508181035f83015261235481846122e0565b905092915050565b5f8060408385031215612372576123716120ad565b5b5f61237f858286016120cb565b9250506020612390858286016120f5565b9150509250929050565b6123a381612109565b82525050565b5f6020820190506123bc5f83018461239a565b92915050565b5f602082840312156123d7576123d66120ad565b5b5f6123e4848285016120cb565b91505092915050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612437826123f1565b810181811067ffffffffffffffff8211171561245657612455612401565b5b80604052505050565b5f6124686120a4565b9050612474828261242e565b919050565b5f67ffffffffffffffff82111561249357612492612401565b5b602082029050602081019050919050565b5f80fd5b5f6124ba6124b584612479565b61245f565b905080838252602082019050602084028301858111156124dd576124dc6124a4565b5b835b8181101561250657806124f288826120cb565b8452602084019350506020810190506124df565b5050509392505050565b5f82601f830112612524576125236123ed565b5b81356125348482602086016124a8565b91505092915050565b5f67ffffffffffffffff82111561255757612556612401565b5b602082029050602081019050919050565b5f61257a6125758461253d565b61245f565b9050808382526020820190506020840283018581111561259d5761259c6124a4565b5b835b818110156125c657806125b288826120f5565b84526020840193505060208101905061259f565b5050509392505050565b5f82601f8301126125e4576125e36123ed565b5b81356125f4848260208601612568565b91505092915050565b5f805f60608486031215612614576126136120ad565b5b5f84013567ffffffffffffffff811115612631576126306120b1565b5b61263d86828701612510565b935050602084013567ffffffffffffffff81111561265e5761265d6120b1565b5b61266a868287016125d0565b925050604061267b868287016120f5565b9150509250925092565b5f806040838503121561269b5761269a6120ad565b5b5f83013567ffffffffffffffff8111156126b8576126b76120b1565b5b6126c485828601612510565b925050602083013567ffffffffffffffff8111156126e5576126e46120b1565b5b6126f1858286016125d0565b9150509250929050565b5f82825260208201905092915050565b7f546f6b656e20616464726573732063616e6e6f74206265207a65726f000000005f82015250565b5f61273f601c836126fb565b915061274a8261270b565b602082019050919050565b5f6020820190508181035f83015261276c81612733565b9050919050565b5f60ff82169050919050565b61278881612773565b8114612792575f80fd5b50565b5f815190506127a38161277f565b92915050565b5f602082840312156127be576127bd6120ad565b5b5f6127cb84828501612795565b91505092915050565b5f6080820190506127e75f83018761204b565b6127f4602083018661207c565b612801604083018561207c565b61280e606083018461239a565b95945050505050565b7f496e76616c69642072616e6765000000000000000000000000000000000000005f82015250565b5f61284b600d836126fb565b915061285682612817565b602082019050919050565b5f6020820190508181035f8301526128788161283f565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6128b682612073565b91506128c183612073565b92508282039050818111156128d9576128d861287f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f496e73756666696369656e742045746865722062616c616e63650000000000005f82015250565b5f612940601a836126fb565b915061294b8261290c565b602082019050919050565b5f6020820190508181035f83015261296d81612934565b9050919050565b5f81519050612982816120df565b92915050565b5f6020828403121561299d5761299c6120ad565b5b5f6129aa84828501612974565b91505092915050565b7f496e73756666696369656e7420746f6b656e2062616c616e63650000000000005f82015250565b5f6129e7601a836126fb565b91506129f2826129b3565b602082019050919050565b5f6020820190508181035f830152612a14816129db565b9050919050565b7f50726573616c65206973206e6f7420696e6163746976650000000000000000005f82015250565b5f612a4f6017836126fb565b9150612a5a82612a1b565b602082019050919050565b5f6020820190508181035f830152612a7c81612a43565b9050919050565b7f50726573616c65206973206e6f742061637469766500000000000000000000005f82015250565b5f612ab76015836126fb565b9150612ac282612a83565b602082019050919050565b5f6020820190508181035f830152612ae481612aab565b9050919050565b7f546f6b656e206973206e6f7420616363657074656400000000000000000000005f82015250565b5f612b1f6015836126fb565b9150612b2a82612aeb565b602082019050919050565b5f6020820190508181035f830152612b4c81612b13565b9050919050565b5f8160011c9050919050565b5f808291508390505b6001851115612ba857808604811115612b8457612b8361287f565b5b6001851615612b935780820291505b8081029050612ba185612b53565b9450612b68565b94509492505050565b5f82612bc05760019050612c7b565b81612bcd575f9050612c7b565b8160018114612be35760028114612bed57612c1c565b6001915050612c7b565b60ff841115612bff57612bfe61287f565b5b8360020a915084821115612c1657612c1561287f565b5b50612c7b565b5060208310610133831016604e8410600b8410161715612c515782820a905083811115612c4c57612c4b61287f565b5b612c7b565b612c5e8484846001612b5f565b92509050818404811115612c7557612c7461287f565b5b81810290505b9392505050565b5f612c8c82612073565b9150612c9783612073565b9250612cc47fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612bb1565b905092915050565b5f612cd682612073565b9150612ce183612073565b9250828202612cef81612073565b91508282048414831517612d0657612d0561287f565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612d4482612073565b9150612d4f83612073565b925082612d5f57612d5e612d0d565b5b828204905092915050565b7f546f6b656e20616e6420707269636520617272617973206d69736d61746368005f82015250565b5f612d9e601f836126fb565b9150612da982612d6a565b602082019050919050565b5f6020820190508181035f830152612dcb81612d92565b9050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f612e068383612272565b60208301905092915050565b5f602082019050919050565b5f612e2882612dd2565b612e328185612ddc565b9350612e3d83612dec565b805f5b83811015612e6d578151612e548882612dfb565b9750612e5f83612e12565b925050600181019050612e40565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f612eae8383612281565b60208301905092915050565b5f602082019050919050565b5f612ed082612e7a565b612eda8185612e84565b9350612ee583612e94565b805f5b83811015612f15578151612efc8882612ea3565b9750612f0783612eba565b925050600181019050612ee8565b5085935050505092915050565b5f6060820190508181035f830152612f3a8186612e1e565b90508181036020830152612f4e8185612ec6565b9050612f5d604083018461207c565b949350505050565b7f315866657250726573616c653a20496e76616c696420707572636861736520615f8201527f6d6f756e74000000000000000000000000000000000000000000000000000000602082015250565b5f612fbf6025836126fb565b9150612fca82612f65565b604082019050919050565b5f6020820190508181035f830152612fec81612fb3565b9050919050565b5f612ffd82612073565b915061300883612073565b92508282019050808211156130205761301f61287f565b5b92915050565b7f496e73756666696369656e7420746f6b656e732072656d61696e696e670000005f82015250565b5f61305a601d836126fb565b915061306582613026565b602082019050919050565b5f6020820190508181035f8301526130878161304e565b9050919050565b5f6040820190506130a15f83018561207c565b6130ae602083018461207c565b9392505050565b5f6060820190506130c85f83018661204b565b6130d5602083018561204b565b6130e2604083018461207c565b949350505050565b5f6040820190506130fd5f83018561204b565b61310a602083018461207c565b9392505050565b5f8151905061311f81612114565b92915050565b5f6020828403121561313a576131396120ad565b5b5f61314784828501613111565b91505092915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f61317c82613150565b613186818561315a565b9350613196818560208601613164565b80840191505092915050565b5f6131ad8284613172565b91508190509291505056fea26469706673582212200a5f24828e296a223de39ecc9f053a7b09aee6ada176c1acffcedaa7f121e26a64736f6c63430008190033

Verified Source Code Full Match

Compiler: v0.8.25+commit.b61c2a91 EVM: cancun Optimization: No
XferPresale.sol 822 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

}

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

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

library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

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

    /**
     * @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 AddressInsufficientBalance(address(this));
        }

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

    /**
     * @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
     * {FailedInnerCall} 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 AddressInsufficientBalance(address(this));
        }
        (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 {FailedInnerCall}) 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 {FailedInnerCall} 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 {FailedInnerCall}.
     */
    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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

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

library SafeERC20 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 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.
     */
    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.
     */
    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.
     */
    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 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).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            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 silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(
        IERC20 token,
        bytes memory data
    ) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success &&
            (returndata.length == 0 || abi.decode(returndata, (bool))) &&
            address(token).code.length > 0;
    }
}

interface IERC20Metadata is IERC20 {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}

contract XferPresale is Ownable, ReentrancyGuard {
    using SafeERC20 for IERC20;
    using SafeERC20 for IERC20Metadata;

    uint256 public tokenRate;

    address public presaleToken;
    uint public tokenDecimals;

    uint256 public availableTokens;

    mapping(address => bool) public acceptedTokens;

    mapping(address => uint256) public tokenPrice;

    bool public presaleActive;

    address[] public participants;

    mapping(address => bool) public hasParticipated;
    mapping(address => uint256) public participantAmount;

    uint256 public totalParticipants;
    uint256 public totalTokensSold;

    address public immutable devAddress;
    address public immutable icoAddress;

    struct ParticipantInfo {
        address participant;
        uint amount;
    }

    event TokenPurchased(
        address indexed buyer,
        address indexed paymentToken,
        uint256 paymentAmount,
        uint256 tokenAmount
    );
    event PresaleDetailsSet(address presaleToken, uint256 availableTokens, uint256 tokenRate, bool presaleActive);
    event TokenRatesUpdated(address[] tokens, uint256[] prices, uint256 newRate);

    constructor(
        address _icoAddress,
        address _devAddress
    ) Ownable(msg.sender) {
	    require(_icoAddress != address(0), "Invalid ICO address");
        require(_devAddress != address(0), "Invalid Dev address");

        presaleActive = false;
        icoAddress = _icoAddress;
        devAddress = _devAddress;
    }

    modifier presaleActiveOnly() {
        require(presaleActive == true, "Presale is not active");
        _;
    }

    modifier presaleInactiveOnly() {
        require(presaleActive == false, "Presale is not inactive");
        _;
    }

    function setPresaleInfo(
    	address _presaleToken,
        uint256 _availableTokens,
        uint256 _tokenRate,
        bool _presaleActive
    ) external onlyOwner nonReentrant {
    	 require(_tokenRate != 0);
	require(_presaleToken != address(0), "Token address cannot be zero");

	tokenRate = _tokenRate;
        presaleToken = _presaleToken;
        presaleActive = _presaleActive;
        tokenDecimals = IERC20Metadata(_presaleToken).decimals();
        availableTokens = _availableTokens;

    	emit PresaleDetailsSet(_presaleToken, _availableTokens, _tokenRate, _presaleActive);

    	IERC20(_presaleToken).safeTransferFrom(msg.sender, address(this), _availableTokens);
    }


    function endPresale() external onlyOwner presaleActiveOnly {
        presaleActive = false;
    }

    function resumePresale() external onlyOwner presaleInactiveOnly {
        presaleActive = true;
    }

    function addAcceptedTokens(
        address[] memory _tokens,
        uint256[] memory _prices
    ) external onlyOwner {
        require(
            _tokens.length == _prices.length,
            "Token and price arrays mismatch"
        );

        for (uint256 i = 0; i < _tokens.length; i++) {
            require(_prices[i] != 0);
            acceptedTokens[_tokens[i]] = true;
            tokenPrice[_tokens[i]] = _prices[i];
        }
    }

    function updateAcceptedTokenStatus(address token, bool newStatus) public onlyOwner {
    	acceptedTokens[token] = newStatus;
    }

    function updateTokenRates(
        address[] memory _tokens,
        uint256[] memory _prices,
        uint256 _newRate
    ) external onlyOwner {
        require(
            _tokens.length == _prices.length,
            "Token and price arrays mismatch"
        );

        if (_newRate != 0) {
            tokenRate = _newRate;
        }

        for (uint256 i = 0; i < _tokens.length; i++) {
            require(acceptedTokens[_tokens[i]] == true);
            require(_prices[i] != 0);
            tokenPrice[_tokens[i]] = _prices[i];
        }

	emit TokenRatesUpdated(_tokens, _prices, _newRate);
    }

    function calculateTokenAmount(
        address token,
        uint256 amount
    ) public view returns (uint256) {
        uint256 tokenAmount;
        if (token != address(0)) {
            require(
                acceptedTokens[token] == true,
                "Token is not accepted"
            );
            uint256 price = tokenPrice[token];
            tokenAmount = (amount * (10 ** tokenDecimals)) / (price);
        } else {
            tokenAmount = (amount * (10 ** tokenDecimals)) / (tokenRate);
        }
        return tokenAmount;
    }

    function calculatePaymentAmount(
        address token,
        uint256 amount
    ) public view returns (uint256) {
        uint256 paymentAmount;
        if (token != address(0)) {
            require(
                acceptedTokens[token] == true,
                "Token is not accepted"
            );
            uint256 price = tokenPrice[token];
            paymentAmount = (amount * (price)) / (10 ** tokenDecimals);
        } else {
            paymentAmount = (amount * (tokenRate)) / (10 ** tokenDecimals);
        }
        return paymentAmount;
    }

    function transferEth(uint256 _amount) internal {
        uint256 devShare = (_amount * 5) / 100;
        payable(devAddress).transfer(devShare);
        payable(icoAddress).transfer(_amount - devShare);
    }

    function transferTokens(address _token, uint256 _amount) internal {
        uint256 devShare = (_amount * 5) / 100;
        IERC20(_token).safeTransferFrom(
            msg.sender,
            devAddress,
            devShare
        );
        IERC20(_token).safeTransferFrom(
            msg.sender,
            icoAddress,
            _amount - devShare
        );
    }

    function buyXferTokens(
        address _token,
        uint256 _amount
    ) external payable presaleActiveOnly nonReentrant {

        uint256 paymentAmount = _token != address(0) ? _amount : msg.value;
        uint256 purchasedTokens = calculateTokenAmount(_token, paymentAmount);

        require(purchasedTokens != 0, "1XferPresale: Invalid purchase amount");
        require(
            (totalTokensSold + purchasedTokens) <= availableTokens,
            "Insufficient tokens remaining"
        );

        totalTokensSold += purchasedTokens;

        if (!hasParticipated[msg.sender]) {
            participants.push(msg.sender);
            hasParticipated[msg.sender] = true;
            totalParticipants += 1;
        }

        participantAmount[msg.sender] += purchasedTokens;

	emit TokenPurchased(msg.sender, _token, paymentAmount, purchasedTokens);

	if (_token != address(0)) {
            transferTokens(_token, _amount);
        } else {
            transferEth(msg.value);
        }

	IERC20(presaleToken).safeTransfer(msg.sender, purchasedTokens);
    }

    function getParticipantsInfo(
        uint _from,
        uint _to
    ) external view returns (ParticipantInfo[] memory) {
        require(_from < _to, "Invalid range");

        uint to = _to > totalParticipants ? totalParticipants : _to;
        uint from = _from > totalParticipants ? totalParticipants : _from;

        ParticipantInfo[] memory participantInfos = new ParticipantInfo[](to - from);

	for (uint i = from; i < to; i++) {
        	participantInfos[i - from] = ParticipantInfo(participants[i], participantAmount[participants[i]]);
    	}

        return participantInfos;
    }

    function withdrawPresaleFunds(address token, uint256 amount) external onlyOwner {
        if (token == address(0)) {
            uint256 balance = address(this).balance;
            require(
                balance >= amount,
                "Insufficient Ether balance"
            );
            payable(owner()).transfer(amount);
        } else {
            uint256 balance = IERC20(token).balanceOf(address(this));
            require(
                balance >= amount,
                "Insufficient token balance"
            );
            IERC20(token).safeTransfer(owner(), amount);
        }
    }
}

Read Contract

acceptedTokens 0x82dc4a05 → bool
availableTokens 0x69bb4dc2 → uint256
calculatePaymentAmount 0xf3d71853 → uint256
calculateTokenAmount 0xaac61a1f → uint256
devAddress 0x3ad10ef6 → address
getParticipantsInfo 0x4ebafbc4 → tuple[]
hasParticipated 0xb4fb3ee3 → bool
icoAddress 0x788ce6f2 → address
owner 0x8da5cb5b → address
participantAmount 0x5e337fc1 → uint256
participants 0x35c1d349 → address
presaleActive 0x53135ca0 → bool
presaleToken 0x24ffea1a → address
tokenDecimals 0x3b97e856 → uint256
tokenPrice 0x84ba3f69 → uint256
tokenRate 0x31711884 → uint256
totalParticipants 0xa26dbf26 → uint256
totalTokensSold 0x63b20117 → uint256

Write Contract 10 functions

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

addAcceptedTokens 0xe9691ade
address[] _tokens
uint256[] _prices
buyXferTokens 0xf16f0116
address _token
uint256 _amount
endPresale 0xa43be57b
No parameters
renounceOwnership 0x715018a6
No parameters
resumePresale 0x54f63ee5
No parameters
setPresaleInfo 0x354e7f1c
address _presaleToken
uint256 _availableTokens
uint256 _tokenRate
bool _presaleActive
transferOwnership 0xf2fde38b
address newOwner
updateAcceptedTokenStatus 0x420dc9b5
address token
bool newStatus
updateTokenRates 0xe0b2b642
address[] _tokens
uint256[] _prices
uint256 _newRate
withdrawPresaleFunds 0x4f737520
address token
uint256 amount

Recent Transactions

This address has 1 on-chain transactions, but only 1.2% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →