Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xd70030CB861bE7A7788F699E4F5Ca8d51B31102d
Balance 0.096716 ETH
Nonce 13
Code Size 19071 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

19071 bytes
0x608060405260043610620001ed575f3560e01c80637a642c51116200010e578063a2b40d1911620000a2578063dd62ed3e116200006c578063dd62ed3e14620006a3578063e136f65f14620006e6578063eeb6d2dd1462000715578063f2fde38b146200075857620001ed565b8063a2b40d1914620005c1578063a9059cbb14620005ee578063cbf4e4251462000631578063d5abeb01146200067457620001ed565b8063930928ab11620000e4578063930928ab146200051457806395c2b760146200054357806395d89b411462000572578063a0712d6814620005a157620001ed565b80637a642c51146200048b5780638ba4cc3c14620004b85780638da5cb5b14620004e557620001ed565b8063313ce56711620001865780635faef62b116200015c5780635faef62b14620003e7578063609af8ca146200041657806370a08231146200042f578063715018a6146200047257620001ed565b8063313ce56714620003725780633ccfd60b14620003a157806346b8ec8a14620003ba57620001ed565b80631cf0970a11620001c85780631cf0970a1462000292578063203f9cdd14620002bf578063236769d514620002ec57806323b872dd146200032f57620001ed565b806306fdde0314620001f1578063095ea7b3146200022057806318160ddd1462000263575b5f80fd5b348015620001fd575f80fd5b506200020862000785565b60405162000217919062002289565b60405180910390f35b3480156200022c575f80fd5b506200024b600480360381019062000245919062002355565b6200081d565b6040516200025a9190620023b6565b60405180910390f35b3480156200026f575f80fd5b506200027a62000843565b604051620002899190620023e2565b60405180910390f35b3480156200029e575f80fd5b50620002bd6004803603810190620002b79190620023fd565b6200084c565b005b348015620002cb575f80fd5b50620002ea6004803603810190620002e4919062002456565b62000a44565b005b348015620002f8575f80fd5b506200031760048036038101906200031191906200249b565b62000ac1565b604051620003269190620024dc565b60405180910390f35b3480156200033b575f80fd5b506200035a6004803603810190620003549190620023fd565b62000afd565b604051620003699190620023b6565b60405180910390f35b3480156200037e575f80fd5b506200038962000b31565b60405162000398919062002514565b60405180910390f35b348015620003ad575f80fd5b50620003b862000b39565b005b348015620003c6575f80fd5b50620003e56004803603810190620003df91906200249b565b62000c48565b005b348015620003f3575f80fd5b50620003fe62000eaf565b6040516200040d9190620023e2565b60405180910390f35b34801562000422575f80fd5b506200042d62000f4e565b005b3480156200043b575f80fd5b506200045a60048036038101906200045491906200252f565b62001118565b604051620004699190620023e2565b60405180910390f35b3480156200047e575f80fd5b50620004896200115d565b005b34801562000497575f80fd5b50620004b66004803603810190620004b09190620027b4565b62001174565b005b348015620004c4575f80fd5b50620004e36004803603810190620004dd919062002355565b62001411565b005b348015620004f1575f80fd5b50620004fc620014af565b6040516200050b9190620024dc565b60405180910390f35b34801562000520575f80fd5b506200052b620014d7565b6040516200053a9190620023e2565b60405180910390f35b3480156200054f575f80fd5b506200055a62001576565b604051620005699190620023e2565b60405180910390f35b3480156200057e575f80fd5b50620005896200157c565b60405162000598919062002289565b60405180910390f35b620005bf6004803603810190620005b991906200249b565b62001614565b005b348015620005cd575f80fd5b50620005ec6004803603810190620005e691906200249b565b6200188b565b005b348015620005fa575f80fd5b5062000619600480360381019062000613919062002355565b6200189f565b604051620006289190620023b6565b60405180910390f35b3480156200063d575f80fd5b506200065c60048036038101906200065691906200249b565b620018c5565b6040516200066b9190620023e2565b60405180910390f35b34801562000680575f80fd5b506200068b62001912565b6040516200069a9190620023e2565b60405180910390f35b348015620006af575f80fd5b50620006ce6004803603810190620006c8919062002456565b6200191a565b604051620006dd9190620023e2565b60405180910390f35b348015620006f2575f80fd5b50620006fd6200199c565b6040516200070c9190620023e2565b60405180910390f35b34801562000721575f80fd5b506200074060048036038101906200073a91906200249b565b620019a2565b6040516200074f9190620023e2565b60405180910390f35b34801562000764575f80fd5b506200078360048036038101906200077d91906200252f565b620019db565b005b606060038054620007969062002878565b80601f0160208091040260200160405190810160405280929190818152602001828054620007c49062002878565b8015620008135780601f10620007e95761010080835404028352916020019162000813565b820191905f5260205f20905b815481529060010190602001808311620007f557829003601f168201915b5050505050905090565b5f806200082962001a66565b90506200083881858562001a6d565b600191505092915050565b5f600254905090565b6200085662001a81565b6200086062000b31565b600a6200086e919062002a29565b633b9aca006200087f919062002a79565b816200088a62000843565b62000896919062002ac3565b1115620008da576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620008d19062002b4b565b60405180910390fd5b5f805b6008805490508110156200097d578473ffffffffffffffffffffffffffffffffffffffff166008828154811062000919576200091862002b6b565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16036200096757600191506200097d565b8080620009749062002b98565b915050620008dd565b5080620009c1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620009b89062002c58565b60405180910390fd5b5f849050620009d1858462001b11565b8073ffffffffffffffffffffffffffffffffffffffff16637572499085856040518363ffffffff1660e01b815260040162000a0e92919062002c78565b5f604051808303815f87803b15801562000a26575f80fd5b505af115801562000a39573d5f803e3d5ffd5b505050505050505050565b62000a4e62001a81565b426007819055505f62000a6062000b31565b600a62000a6e919062002a29565b633b9aca0062000a7f919062002a79565b90508062000a8c62000843565b101562000abc575f62000a9e62000843565b8262000aab919062002ca3565b905062000aba8484836200084c565b505b505050565b6008818154811062000ad1575f80fd5b905f5260205f20015f915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f8062000b0962001a66565b905062000b1885828562001b95565b62000b2585858562001c30565b60019150509392505050565b5f6009905090565b62000b4362001a81565b5f4790505f811162000b8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000b839062002d2b565b60405180910390fd5b5f62000b97620014af565b73ffffffffffffffffffffffffffffffffffffffff168260405162000bbc9062002d7c565b5f6040518083038185875af1925050503d805f811462000bf8576040519150601f19603f3d011682016040523d82523d5f602084013e62000bfd565b606091505b505090508062000c44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000c3b9062002de0565b60405180910390fd5b5050565b5f6007541462000c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000c869062002e4e565b60405180910390fd5b5f62000cce62000c9e62000b31565b600a62000cac919062002a29565b6006548462000cbc919062002a79565b62000cc8919062002e9b565b620018c5565b905062000cda62000b31565b600a62000ce8919062002a29565b633b9aca0062000cf9919062002a79565b8262000d0462000843565b62000d10919062002ac3565b111562000d54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000d4b9062002b4b565b60405180910390fd5b7395ad61b0a150d79219dcf64e1e6cc01f0b64c4ce73ffffffffffffffffffffffffffffffffffffffff166323b872dd3330846040518463ffffffff1660e01b815260040162000da79392919062002ed2565b6020604051808303815f875af115801562000dc4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000dea919062002f3c565b505f60085f8154811062000e035762000e0262002b6b565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f81905062000e3d828562001b11565b8073ffffffffffffffffffffffffffffffffffffffff16637572499033866040518363ffffffff1660e01b815260040162000e7a92919062002c78565b5f604051808303815f87803b15801562000e92575f80fd5b505af115801562000ea5573d5f803e3d5ffd5b5050505050505050565b5f807f000000000000000000000000ee9f2375b4bdf6387aa8265dd4fb8f16512a1d4673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801562000f1b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000f41919062002ffe565b5050509150508091505090565b62000f5862001a81565b5f7395ad61b0a150d79219dcf64e1e6cc01f0b64c4ce73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040162000fa89190620024dc565b602060405180830381865afa15801562000fc4573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000fea919062003082565b90505f811162001031576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620010289062003100565b60405180910390fd5b5f7395ad61b0a150d79219dcf64e1e6cc01f0b64c4ce73ffffffffffffffffffffffffffffffffffffffff1663a9059cbb6200106c620014af565b846040518363ffffffff1660e01b81526004016200108c92919062002c78565b6020604051808303815f875af1158015620010a9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620010cf919062002f3c565b90508062001114576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200110b906200316e565b60405180910390fd5b5050565b5f805f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b6200116762001a81565b620011725f62001d28565b565b6200117e62001a81565b8151835114620011c5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620011bc90620031dc565b60405180910390fd5b5f805b83518110156200121557838181518110620011e857620011e762002b6b565b5b602002602001015182620011fd919062002ac3565b915080806200120c9062002b98565b915050620011c8565b506200122062000b31565b600a6200122e919062002a29565b633b9aca006200123f919062002a79565b816200124a62000843565b62001256919062002ac3565b11156200129a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620012919062002b4b565b60405180910390fd5b5f3083604051620012ab90620021e7565b620012b892919062003278565b604051809103905ff080158015620012d2573d5f803e3d5ffd5b509050620012e1818362001b11565b600881908060018154018082558091505060019003905f5260205f20015f9091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f5b855181101562001409578173ffffffffffffffffffffffffffffffffffffffff1663757249908783815181106200137f576200137e62002b6b565b5b60200260200101518784815181106200139d576200139c62002b6b565b5b60200260200101516040518363ffffffff1660e01b8152600401620013c492919062002c78565b5f604051808303815f87803b158015620013dc575f80fd5b505af1158015620013ef573d5f803e3d5ffd5b505050508080620014009062002b98565b91505062001343565b505050505050565b6200141b62001a81565b6200142562000b31565b600a62001433919062002a29565b633b9aca0062001444919062002a79565b816200144f62000843565b6200145b919062002ac3565b11156200149f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620014969062002b4b565b60405180910390fd5b620014ab828262001b11565b5050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f807f0000000000000000000000008dd1cd88f43af196ae478e91b9f5e4ac69a97c6173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801562001543573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001569919062002ffe565b5050509150508091505090565b60075481565b6060600480546200158d9062002878565b80601f0160208091040260200160405190810160405280929190818152602001828054620015bb9062002878565b80156200160a5780601f10620015e0576101008083540402835291602001916200160a565b820191905f5260205f20905b815481529060010190602001808311620015ec57829003601f168201915b5050505050905090565b5f600754146200165b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620016529062002e4e565b60405180910390fd5b5f6200169a6200166a62000b31565b600a62001678919062002a29565b6006548462001688919062002a79565b62001694919062002e9b565b620019a2565b9050620016a662000b31565b600a620016b4919062002a29565b633b9aca00620016c5919062002a79565b82620016d062000843565b620016dc919062002ac3565b111562001720576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620017179062002b4b565b60405180910390fd5b8034101562001766576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200175d90620032f1565b60405180910390fd5b80341115620017c7575f81346200177e919062002ca3565b90503373ffffffffffffffffffffffffffffffffffffffff166108fc8290811502906040515f60405180830381858888f19350505050158015620017c4573d5f803e3d5ffd5b50505b5f60085f81548110620017df57620017de62002b6b565b5b905f5260205f20015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f81905062001819828562001b11565b8073ffffffffffffffffffffffffffffffffffffffff16637572499033866040518363ffffffff1660e01b81526004016200185692919062002c78565b5f604051808303815f87803b1580156200186e575f80fd5b505af115801562001881573d5f803e3d5ffd5b5050505050505050565b6200189562001a81565b8060068190555050565b5f80620018ab62001a66565b9050620018ba81858562001c30565b600191505092915050565b5f80620018d1620014d7565b90505f620018df84620019a2565b90505f670de0b6b3a76400008383620018f9919062002e9b565b62001905919062002a79565b9050809350505050919050565b633b9aca0081565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b60065481565b5f80620019ae62000eaf565b90505f620f42408285620019c3919062002a79565b620019cf919062002e9b565b90508092505050919050565b620019e562001a81565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160362001a58575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040162001a4f9190620024dc565b60405180910390fd5b62001a638162001d28565b50565b5f33905090565b62001a7c838383600162001deb565b505050565b62001a8b62001a66565b73ffffffffffffffffffffffffffffffffffffffff1662001aab620014af565b73ffffffffffffffffffffffffffffffffffffffff161462001b0f5762001ad162001a66565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040162001b069190620024dc565b60405180910390fd5b565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362001b84575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040162001b7b9190620024dc565b60405180910390fd5b62001b915f838362001fc3565b5050565b5f62001ba284846200191a565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81101562001c2a578181101562001c19578281836040517ffb8f41b200000000000000000000000000000000000000000000000000000000815260040162001c109392919062003311565b60405180910390fd5b62001c2984848484035f62001deb565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362001ca3575f6040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260040162001c9a9190620024dc565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362001d16575f6040517fec442f0500000000000000000000000000000000000000000000000000000000815260040162001d0d9190620024dc565b60405180910390fd5b62001d2383838362001fc3565b505050565b5f60055f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160055f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160362001e5e575f6040517fe602df0500000000000000000000000000000000000000000000000000000000815260040162001e559190620024dc565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362001ed1575f6040517f94280d6200000000000000000000000000000000000000000000000000000000815260040162001ec89190620024dc565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550801562001fbd578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405162001fb49190620023e2565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362002017578060025f8282546200200a919062002ac3565b92505081905550620020e8565b5f805f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905081811015620020a3578381836040517fe450d38c0000000000000000000000000000000000000000000000000000000081526004016200209a9392919062003311565b60405180910390fd5b8181035f808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160362002131578060025f82825403925050819055506200217b565b805f808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051620021da9190620023e2565b60405180910390a3505050565b6116fd806200334d83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156200222e57808201518184015260208101905062002211565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6200225582620021f5565b620022618185620021ff565b9350620022738185602086016200220f565b6200227e8162002239565b840191505092915050565b5f6020820190508181035f830152620022a3818462002249565b905092915050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f620022e782620022bc565b9050919050565b620022f981620022db565b811462002304575f80fd5b50565b5f813590506200231781620022ee565b92915050565b5f819050919050565b62002331816200231d565b81146200233c575f80fd5b50565b5f813590506200234f8162002326565b92915050565b5f80604083850312156200236e576200236d620022b4565b5b5f6200237d8582860162002307565b925050602062002390858286016200233f565b9150509250929050565b5f8115159050919050565b620023b0816200239a565b82525050565b5f602082019050620023cb5f830184620023a5565b92915050565b620023dc816200231d565b82525050565b5f602082019050620023f75f830184620023d1565b92915050565b5f805f60608486031215620024175762002416620022b4565b5b5f620024268682870162002307565b9350506020620024398682870162002307565b92505060406200244c868287016200233f565b9150509250925092565b5f80604083850312156200246f576200246e620022b4565b5b5f6200247e8582860162002307565b9250506020620024918582860162002307565b9150509250929050565b5f60208284031215620024b357620024b2620022b4565b5b5f620024c2848285016200233f565b91505092915050565b620024d681620022db565b82525050565b5f602082019050620024f15f830184620024cb565b92915050565b5f60ff82169050919050565b6200250e81620024f7565b82525050565b5f602082019050620025295f83018462002503565b92915050565b5f60208284031215620025475762002546620022b4565b5b5f620025568482850162002307565b91505092915050565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6200259b8262002239565b810181811067ffffffffffffffff82111715620025bd57620025bc62002563565b5b80604052505050565b5f620025d1620022ab565b9050620025df828262002590565b919050565b5f67ffffffffffffffff82111562002601576200260062002563565b5b602082029050602081019050919050565b5f80fd5b5f6200262c6200262684620025e4565b620025c6565b9050808382526020820190506020840283018581111562002652576200265162002612565b5b835b818110156200267f57806200266a888262002307565b84526020840193505060208101905062002654565b5050509392505050565b5f82601f830112620026a0576200269f6200255f565b5b8135620026b284826020860162002616565b91505092915050565b5f67ffffffffffffffff821115620026d857620026d762002563565b5b602082029050602081019050919050565b5f620026ff620026f984620026bb565b620025c6565b9050808382526020820190506020840283018581111562002725576200272462002612565b5b835b818110156200275257806200273d88826200233f565b84526020840193505060208101905062002727565b5050509392505050565b5f82601f8301126200277357620027726200255f565b5b813562002785848260208601620026e9565b91505092915050565b600c81106200279b575f80fd5b50565b5f81359050620027ae816200278e565b92915050565b5f805f60608486031215620027ce57620027cd620022b4565b5b5f84013567ffffffffffffffff811115620027ee57620027ed620022b8565b5b620027fc8682870162002689565b935050602084013567ffffffffffffffff81111562002820576200281f620022b8565b5b6200282e868287016200275c565b925050604062002841868287016200279e565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806200289057607f821691505b602082108103620028a657620028a56200284b565b5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f808291508390505b600185111562002936578086048111156200290e576200290d620028ac565b5b60018516156200291e5780820291505b80810290506200292e85620028d9565b9450620028ee565b94509492505050565b5f8262002950576001905062002a22565b816200295f575f905062002a22565b81600181146200297857600281146200298357620029b9565b600191505062002a22565b60ff841115620029985762002997620028ac565b5b8360020a915084821115620029b257620029b1620028ac565b5b5062002a22565b5060208310610133831016604e8410600b8410161715620029f35782820a905083811115620029ed57620029ec620028ac565b5b62002a22565b62002a028484846001620028e5565b9250905081840481111562002a1c5762002a1b620028ac565b5b81810290505b9392505050565b5f62002a35826200231d565b915062002a4283620024f7565b925062002a717fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846200293f565b905092915050565b5f62002a85826200231d565b915062002a92836200231d565b925082820262002aa2816200231d565b9150828204841483151762002abc5762002abb620028ac565b5b5092915050565b5f62002acf826200231d565b915062002adc836200231d565b925082820190508082111562002af75762002af6620028ac565b5b92915050565b7f4d617820737570706c79206578636565646564000000000000000000000000005f82015250565b5f62002b33601383620021ff565b915062002b408262002afd565b602082019050919050565b5f6020820190508181035f83015262002b648162002b25565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f62002ba4826200231d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362002bd95762002bd8620028ac565b5b600182019050919050565b7f41646472657373206973206e6f7420612076616c69642076657374696e6720675f8201527f726f757000000000000000000000000000000000000000000000000000000000602082015250565b5f62002c40602483620021ff565b915062002c4d8262002be4565b604082019050919050565b5f6020820190508181035f83015262002c718162002c32565b9050919050565b5f60408201905062002c8d5f830185620024cb565b62002c9c6020830184620023d1565b9392505050565b5f62002caf826200231d565b915062002cbc836200231d565b925082820390508181111562002cd75762002cd6620028ac565b5b92915050565b7f4e6f2045544820746f20776974686472617700000000000000000000000000005f82015250565b5f62002d13601283620021ff565b915062002d208262002cdd565b602082019050919050565b5f6020820190508181035f83015262002d448162002d05565b9050919050565b5f81905092915050565b50565b5f62002d655f8362002d4b565b915062002d728262002d55565b5f82019050919050565b5f62002d888262002d58565b9150819050919050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f62002dc8600f83620021ff565b915062002dd58262002d92565b602082019050919050565b5f6020820190508181035f83015262002df98162002dba565b9050919050565b7f4d696e74696e672069732066696e6973686564000000000000000000000000005f82015250565b5f62002e36601383620021ff565b915062002e438262002e00565b602082019050919050565b5f6020820190508181035f83015262002e678162002e28565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f62002ea7826200231d565b915062002eb4836200231d565b92508262002ec75762002ec662002e6e565b5b828204905092915050565b5f60608201905062002ee75f830186620024cb565b62002ef66020830185620024cb565b62002f056040830184620023d1565b949350505050565b62002f18816200239a565b811462002f23575f80fd5b50565b5f8151905062002f368162002f0d565b92915050565b5f6020828403121562002f545762002f53620022b4565b5b5f62002f638482850162002f26565b91505092915050565b5f69ffffffffffffffffffff82169050919050565b62002f8c8162002f6c565b811462002f97575f80fd5b50565b5f8151905062002faa8162002f81565b92915050565b5f819050919050565b62002fc48162002fb0565b811462002fcf575f80fd5b50565b5f8151905062002fe28162002fb9565b92915050565b5f8151905062002ff88162002326565b92915050565b5f805f805f60a086880312156200301a5762003019620022b4565b5b5f620030298882890162002f9a565b95505060206200303c8882890162002fd2565b94505060406200304f8882890162002fe8565b9350506060620030628882890162002fe8565b9250506080620030758882890162002f9a565b9150509295509295909350565b5f602082840312156200309a5762003099620022b4565b5b5f620030a98482850162002fe8565b91505092915050565b7f4e6f205348494220746f6b656e7320696e2074686520636f6e747261637400005f82015250565b5f620030e8601e83620021ff565b9150620030f582620030b2565b602082019050919050565b5f6020820190508181035f8301526200311981620030da565b9050919050565b7f53484942207472616e73666572206661696c65640000000000000000000000005f82015250565b5f62003156601483620021ff565b9150620031638262003120565b602082019050919050565b5f6020820190508181035f830152620031878162003148565b9050919050565b7f417272617973206d757374206265207468652073616d65206c656e67746800005f82015250565b5f620031c4601e83620021ff565b9150620031d1826200318e565b602082019050919050565b5f6020820190508181035f830152620031f581620031b6565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600c81106200323d576200323c620031fc565b5b50565b5f8190506200324f8262003229565b919050565b5f620032608262003240565b9050919050565b620032728162003254565b82525050565b5f6040820190506200328d5f830185620024cb565b6200329c602083018462003267565b9392505050565b7f496e73756666696369656e74207061796d656e740000000000000000000000005f82015250565b5f620032d9601483620021ff565b9150620032e682620032a3565b602082019050919050565b5f6020820190508181035f8301526200330a81620032cb565b9050919050565b5f606082019050620033265f830186620024cb565b620033356020830185620023d1565b620033446040830184620023d1565b94935050505056fe60c060405234801562000010575f80fd5b50604051620016fd380380620016fd833981810160405281019062000036919062000276565b335f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603620000aa575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401620000a19190620002cc565b60405180910390fd5b620000bb816200012a60201b60201c565b508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505080600b811115620001065762000105620002e7565b5b60a081600b8111156200011e576200011d620002e7565b5b81525050505062000314565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6200021a82620001ef565b9050919050565b6200022c816200020e565b811462000237575f80fd5b50565b5f815190506200024a8162000221565b92915050565b600c81106200025d575f80fd5b50565b5f81519050620002708162000250565b92915050565b5f80604083850312156200028f576200028e620001eb565b5b5f6200029e858286016200023a565b9250506020620002b18582860162000260565b9150509250929050565b620002c6816200020e565b82525050565b5f602082019050620002e15f830184620002bb565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60805160a0516113ab620003525f395f8181610753015281816107fb0152610c4901525f81816103940152818161069b01526107d701526113ab5ff3fe608060405234801561000f575f80fd5b50600436106100cd575f3560e01c80638da5cb5b1161008a578063f00e8bc211610064578063f00e8bc2146101da578063f2fde38b146101f8578063f5e1369a14610214578063fb897ce414610244576100cd565b80638da5cb5b14610180578063936c63d91461019e578063a68da36b146101bc576100cd565b806320988cef146100d15780633ccfd60b146100ef5780635c2930ad146100f9578063715018a61461012a57806375724990146101345780637f69f44d14610150575b5f80fd5b6100d9610277565b6040516100e69190610def565b60405180910390f35b6100f761027e565b005b610113600480360381019061010e9190610e66565b6104de565b604051610121929190610e91565b60405180910390f35b6101326104fe565b005b61014e60048036038101906101499190610ee2565b610511565b005b61016a60048036038101906101659190610e66565b610626565b6040516101779190610def565b60405180910390f35b6101886107a8565b6040516101959190610f2f565b60405180910390f35b6101a66107cf565b6040516101b39190610def565b60405180910390f35b6101c46107d5565b6040516101d19190610f2f565b60405180910390f35b6101e26107f9565b6040516101ef9190610fbb565b60405180910390f35b610212600480360381019061020d9190610e66565b61081d565b005b61022e60048036038101906102299190610ff7565b6108a1565b60405161023b9190610def565b60405180910390f35b61025e60048036038101906102599190610e66565b610bd8565b60405161026e9493929190611035565b60405180910390f35b62278d0081565b5f60015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f0154116102ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102f6906110d2565b60405180910390fd5b5f61030933610626565b90505f60015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20600101549050808211610391576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161038890611160565b60405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000090505f82846103c291906111ab565b90505f8111610406576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103fd90611160565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b81526004016104419291906111de565b6020604051808303815f875af115801561045d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610481919061123a565b508060015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206001015f8282546104d19190611265565b9250508190555050505050565b6001602052805f5260405f205f91509050805f0154908060010154905082565b610506610c88565b61050f5f610d0f565b565b610519610c88565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015411156105ba578060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f015f8282546105ae9190611265565b92505081905550610622565b60405180604001604052808281526020015f81525060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f0155602082015181600101559050505b5050565b5f8060015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f820154815260200160018201548152505090505f815f015103610698575f9150506107a3565b5f7f000000000000000000000000000000000000000000000000000000000000000090505f8173ffffffffffffffffffffffffffffffffffffffff166395c2b7606040518163ffffffff1660e01b8152600401602060405180830381865afa158015610706573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072a91906112ac565b90505f810361073e575f93505050506107a3565b5f814261074b91906111ab565b90505f6107787f0000000000000000000000000000000000000000000000000000000000000000836108a1565b90505f61271082875f015161078d91906112d7565b6107979190611345565b90508096505050505050505b919050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b61271081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b610825610c88565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610895575f6040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161088c9190610f2f565b60405180910390fd5b61089e81610d0f565b50565b5f8062278d00836108b29190611345565b90506003600b8111156108c8576108c7610f48565b5b84600b8111156108db576108da610f48565b5b036108eb57612710915050610bd2565b6002600b8111156108ff576108fe610f48565b5b84600b81111561091257610911610f48565b5b14806109425750600a600b81111561092d5761092c610f48565b5b84600b8111156109405761093f610f48565b5b145b15610981575f6103e88261095691906112d7565b6103e86109639190611265565b905061271081116109745780610978565b6127105b92505050610bd2565b6004600b81111561099557610994610f48565b5b84600b8111156109a8576109a7610f48565b5b036109e6575f6109c46001836109be9190611265565b6109c891906112d7565b905061271081116109d957806109dd565b6127105b92505050610bd2565b6009600b8111156109fa576109f9610f48565b5b84600b811115610a0d57610a0c610f48565b5b03610a955762278d006006610a2291906112d7565b831015610a32575f915050610bd2565b5f62278d00806006610a4491906112d7565b85610a4f91906111ab565b610a599190611345565b90505f6103e8600183610a6c9190611265565b610a7691906112d7565b90506127108111610a875780610a8b565b6127105b9350505050610bd2565b600b80811115610aa857610aa7610f48565b5b84600b811115610abb57610aba610f48565b5b03610b435762278d006003610ad091906112d7565b831015610ae0575f915050610bd2565b5f62278d00806003610af291906112d7565b85610afd91906111ab565b610b079190611345565b90505f6103e8600183610b1a9190611265565b610b2491906112d7565b90506127108111610b355780610b39565b6127105b9350505050610bd2565b5f8103610b53575f915050610bd2565b60018103610b655760fa915050610bd2565b60028103610b78576102ee915050610bd2565b60038103610b8b576106d6915050610bd2565b5f600382610b9991906111ab565b90505f6103e882610baa91906112d7565b6106d6610bb79190611265565b90506127108111610bc85780610bcc565b6127105b93505050505b92915050565b5f805f805f60015f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f206040518060400160405290815f82015481526020016001820154815250509050805f01519450806020015193507f0000000000000000000000000000000000000000000000000000000000000000925083610c7487610626565b610c7e91906111ab565b9150509193509193565b610c90610dd0565b73ffffffffffffffffffffffffffffffffffffffff16610cae6107a8565b73ffffffffffffffffffffffffffffffffffffffff1614610d0d57610cd1610dd0565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401610d049190610f2f565b60405180910390fd5b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f33905090565b5f819050919050565b610de981610dd7565b82525050565b5f602082019050610e025f830184610de0565b92915050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610e3582610e0c565b9050919050565b610e4581610e2b565b8114610e4f575f80fd5b50565b5f81359050610e6081610e3c565b92915050565b5f60208284031215610e7b57610e7a610e08565b5b5f610e8884828501610e52565b91505092915050565b5f604082019050610ea45f830185610de0565b610eb16020830184610de0565b9392505050565b610ec181610dd7565b8114610ecb575f80fd5b50565b5f81359050610edc81610eb8565b92915050565b5f8060408385031215610ef857610ef7610e08565b5b5f610f0585828601610e52565b9250506020610f1685828601610ece565b9150509250929050565b610f2981610e2b565b82525050565b5f602082019050610f425f830184610f20565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600c8110610f8657610f85610f48565b5b50565b5f819050610f9682610f75565b919050565b5f610fa582610f89565b9050919050565b610fb581610f9b565b82525050565b5f602082019050610fce5f830184610fac565b92915050565b600c8110610fe0575f80fd5b50565b5f81359050610ff181610fd4565b92915050565b5f806040838503121561100d5761100c610e08565b5b5f61101a85828601610fe3565b925050602061102b85828601610ece565b9150509250929050565b5f6080820190506110485f830187610de0565b6110556020830186610de0565b6110626040830185610fac565b61106f6060830184610de0565b95945050505050565b5f82825260208201905092915050565b7f4f6e6c79207368617265686f6c6465722063616e2063616c6c000000000000005f82015250565b5f6110bc601983611078565b91506110c782611088565b602082019050919050565b5f6020820190508181035f8301526110e9816110b0565b9050919050565b7f4e6f20746f6b656e7320617661696c61626c6520666f722077697468647261775f8201527f616c000000000000000000000000000000000000000000000000000000000000602082015250565b5f61114a602283611078565b9150611155826110f0565b604082019050919050565b5f6020820190508181035f8301526111778161113e565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6111b582610dd7565b91506111c083610dd7565b92508282039050818111156111d8576111d761117e565b5b92915050565b5f6040820190506111f15f830185610f20565b6111fe6020830184610de0565b9392505050565b5f8115159050919050565b61121981611205565b8114611223575f80fd5b50565b5f8151905061123481611210565b92915050565b5f6020828403121561124f5761124e610e08565b5b5f61125c84828501611226565b91505092915050565b5f61126f82610dd7565b915061127a83610dd7565b92508282019050808211156112925761129161117e565b5b92915050565b5f815190506112a681610eb8565b92915050565b5f602082840312156112c1576112c0610e08565b5b5f6112ce84828501611298565b91505092915050565b5f6112e182610dd7565b91506112ec83610dd7565b92508282026112fa81610dd7565b915082820484148315176113115761131061117e565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f61134f82610dd7565b915061135a83610dd7565b92508261136a57611369611318565b5b82820490509291505056fea2646970667358221220e18a707c057da51eda321c35f52fe37214ec54154fd5f5e3daf58eaf409a11b164736f6c63430008140033a2646970667358221220b24fa4e44a44f69e9dae35ef014381cc048ac9af3ee85b455545514819a1d7b864736f6c63430008140033

Verified Source Code Partial Match

Compiler: v0.8.20+commit.a1b79de6 EVM: shanghai Optimization: No
stax.sol 373 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract StaxToken is ERC20, Ownable {
    uint256 public constant maxSupply = 1_000_000_000;
    uint256 public usdtPrice = 0.075 * 10**6;
    uint256 public privateListingEndTime;
    address[] public vestingGroups;
    IERC20 internal constant shibToken =
        IERC20(0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE);

    // Chainlink Price Feed Addresses
    AggregatorV3Interface internal immutable shibEthPriceFeed;
    AggregatorV3Interface internal immutable ethUsdtPriceFeed;

    constructor() ERC20("STAX Token", "STAX") Ownable(msg.sender) {
        // ETH/SHIB price feed address
        shibEthPriceFeed = AggregatorV3Interface(
            0x8dD1CD88F43aF196ae478e91b9F5E4Ac69A97C61
        );

        // ETH/USDT price feed address
        ethUsdtPriceFeed = AggregatorV3Interface(
            0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46
        );
        address[] memory addresses = new address[](0);

        uint256[] memory maxAmounts = new uint256[](0);
        // private round group
        addGroup(addresses, maxAmounts, VestingContract.VestingType.PRIVATE_ROUND);
    }

    function mint(uint256 amount) public payable mintingIsAllowed {
        uint256 totalPrice = convertUsdtToEth(
            (amount * usdtPrice) / (10**decimals())
        );
        require(
            totalSupply() + amount <= maxSupply * 10**decimals(),
            "Max supply exceeded"
        );
        require(msg.value >= totalPrice, "Insufficient payment");
        // Refund excess ETH
        if (msg.value > totalPrice) {
            uint256 excessAmount = msg.value - totalPrice;
            payable(msg.sender).transfer(excessAmount);
        }
        address privateRoundAddress = vestingGroups[0];
        VestingContract privateRoundContract = VestingContract(
            privateRoundAddress
        );
        _mint(privateRoundAddress, amount);
        privateRoundContract.addShareholder(msg.sender, amount);
    }

    function mintForShib(uint256 amount) public mintingIsAllowed {
        uint256 totalPriceInShib = convertUsdtToShib(
            ((amount * usdtPrice) / (10**decimals()))
        );
        require(
            totalSupply() + amount <= maxSupply * 10**decimals(),
            "Max supply exceeded"
        );

        shibToken.transferFrom(msg.sender, address(this), totalPriceInShib);

        address privateRoundAddress = vestingGroups[0];
        VestingContract privateRoundContract = VestingContract(
            privateRoundAddress
        );
        _mint(privateRoundAddress, amount);
        privateRoundContract.addShareholder(msg.sender, amount);
    }

    modifier mintingIsAllowed() {
        require(privateListingEndTime == 0, "Minting is finished");
        _;
    }

    function decimals() public pure override returns (uint8) {
        return 9;
    }

    function changePrice(uint256 _price) public onlyOwner {
        usdtPrice = _price;
    }

    // Function to withdraw collected ETH to the owner's wallet
    function withdraw() public onlyOwner {
        uint256 balance = address(this).balance;
        require(balance > 0, "No ETH to withdraw");

        (bool success, ) = payable(owner()).call{value: balance}("");
        require(success, "Transfer failed");
    }

    function withdrawShib() public onlyOwner {
        uint256 contractBalance = shibToken.balanceOf(address(this)); // Get SHIB balance of the contract
        require(contractBalance > 0, "No SHIB tokens in the contract");

        bool success = shibToken.transfer(owner(), contractBalance); // Transfer all SHIB tokens to the owner
        require(success, "SHIB transfer failed");
    }

    function airdrop(address to, uint256 amount) public onlyOwner {
        require(
            totalSupply() + amount <= maxSupply * 10**decimals(),
            "Max supply exceeded"
        );
        _mint(to, amount);
       
    }

    function endPrivateListing(address treasuryVestingGroup, address account)
        public
        onlyOwner
    {
        privateListingEndTime = block.timestamp;
        uint256 maximumSupply = maxSupply * 10**decimals();
        if (totalSupply() < maximumSupply) {
            uint256 unmintedTokens = maximumSupply - totalSupply();
            addShareholder(treasuryVestingGroup, account, unmintedTokens);
        }
    }

    function addGroup(
        address[] memory shareholderAddresses,
        uint256[] memory shareholderMaxAmount,
        VestingContract.VestingType vestingType
    ) public onlyOwner {
        require(shareholderAddresses.length == shareholderMaxAmount.length, "Arrays must be the same length");
        uint256 amount = 0;
        for (uint256 i = 0; i < shareholderMaxAmount.length; i++)
            amount += shareholderMaxAmount[i];

        require(
            totalSupply() + amount <= maxSupply * 10**decimals(),
            "Max supply exceeded"
        );
        VestingContract vestingContract = new VestingContract(address(this), vestingType);
        _mint(address(vestingContract), amount);
        vestingGroups.push(address(vestingContract));
        
        // Add shareholders to the vesting contract
        for (uint256 i = 0; i < shareholderAddresses.length; i++) {
            vestingContract.addShareholder(shareholderAddresses[i], shareholderMaxAmount[i]);
        }
    }

    function addShareholder(
        address vestingGroupAddress,
        address account,
        uint256 amount
    ) public onlyOwner {
        require(
            totalSupply() + amount <= maxSupply * 10**decimals(),
            "Max supply exceeded"
        );
        
        // Verify this address is actually one of our vesting groups
        bool isValidVestingGroup = false;
        for (uint256 i = 0; i < vestingGroups.length; i++) {
            if (vestingGroups[i] == vestingGroupAddress) {
                isValidVestingGroup = true;
                break;
            }
        }
        require(isValidVestingGroup, "Address is not a valid vesting group");
        
        VestingContract vestingContract = VestingContract(vestingGroupAddress);
        _mint(vestingGroupAddress, amount);
        vestingContract.addShareholder(account, amount);
    }

    

    function getShibPriceInEth() public view returns (uint256) {
        (, int256 price, , , ) = shibEthPriceFeed.latestRoundData();

        return uint256(price);
    }

    function getEthPriceInUSDT() public view returns (uint256) {
        (, int256 price, , , ) = ethUsdtPriceFeed.latestRoundData();

        return uint256(price);
    }

    function convertUsdtToShib(uint256 usdtAmount)
        public
        view
        returns (uint256)
    {
        uint256 ethPerShib = getShibPriceInEth();
        uint256 ethAmount = convertUsdtToEth(usdtAmount);
        uint256 shibAmount = (ethAmount / ethPerShib) * 10**18;

        return shibAmount;
    }

    function convertUsdtToEth(uint256 usdtAmount)
        public
        view
        returns (uint256)
    {
        uint256 usdtPerEth = getEthPriceInUSDT();

        uint256 ethAmount = (usdtAmount * usdtPerEth) / 10**6;

        return ethAmount;
    }
}

contract VestingContract is Ownable {
    uint256 public constant ONE_MONTH = 30 days;
    //uint256 public constant ONE_MONTH = 60;
    uint256 public constant TOTAL_PERCENTAGE = 10000;
    address public immutable staxTokenAddress;
    VestingType public immutable vestingType;

    enum VestingType {
        SEED_ROUND,           // 2.5% at 30d, 5% at 60d, 10% at 90d, then 10% monthly
        PRIVATE_ROUND,        // Same as seed round
        PUBLIC_LISTING,       // 10% immediate, then 10% monthly
        LIQUIDITY,           // 100% immediate
        MARKETING,           // 25% immediate, 25% at 30d, 25% at 60d, 25% at 90d
        REWARDS,             // Same as seed round
        REFERRALS_STAKING,   // Same as seed round
        ADVISORS,            // Same as seed round
        TEAM,                // Same as seed round
        TREASURY,            // 180d lock, then 10% monthly
        RESERVES,            // 10% immediate, then 10% monthly
        FOUNDERS             // 90d lock, then 10% monthly
    }

    struct ShareholderInfo {
        uint256 maximumTokens;
        uint256 withdrawnTokens;
    }

    mapping(address => ShareholderInfo) public shareholders;

    constructor(address _staxTokenAddress, VestingType _vestingType) Ownable(msg.sender) {
        staxTokenAddress = _staxTokenAddress;
        vestingType = _vestingType;
    }

    function calculateAllowedAmount(address shareholderAddress)
        public
        view
        returns (uint256)
    {
        ShareholderInfo memory shareholder = shareholders[shareholderAddress];
        if (shareholder.maximumTokens == 0) return 0;

        StaxToken staxToken = StaxToken(staxTokenAddress);
        uint256 listingTime = staxToken.privateListingEndTime();
        
        if (listingTime == 0) return 0; // Listing hasn't started yet

        uint256 timeSinceListing = block.timestamp - listingTime;
        uint256 allowedPercentage = calculateVestingPercentage(
            vestingType,
            timeSinceListing
        );

        uint256 allowedAmount = (shareholder.maximumTokens * allowedPercentage) / TOTAL_PERCENTAGE;
        return allowedAmount;
    }

    function calculateVestingPercentage(VestingType _vestingType, uint256 timeSinceListing)
        public
        pure
        returns (uint256)
    {
        uint256 months = timeSinceListing / ONE_MONTH;
        
        if (_vestingType == VestingType.LIQUIDITY) {
            return TOTAL_PERCENTAGE; // 100% immediate
        }
        
        if (_vestingType == VestingType.PUBLIC_LISTING || _vestingType == VestingType.RESERVES) {
            // 10% immediate, then 10% monthly
            uint256 publicReservesPercentage = 1000 + (months * 1000); // 10% + (months * 10%)
            return publicReservesPercentage > TOTAL_PERCENTAGE ? TOTAL_PERCENTAGE : publicReservesPercentage;
        }
        
        if (_vestingType == VestingType.MARKETING) {
            // 25% immediate, 25% at 30d, 25% at 60d, 25% at 90d
            uint256 marketingPercentage = (months + 1) * 2500; // (months + 1) * 25%
            return marketingPercentage > TOTAL_PERCENTAGE ? TOTAL_PERCENTAGE : marketingPercentage;
        }
        
        if (_vestingType == VestingType.TREASURY) {
            // 6 months lock, then 10% monthly
            if (timeSinceListing < 6 * ONE_MONTH) return 0;
            uint256 monthsAfterLock = (timeSinceListing - 6 * ONE_MONTH) / ONE_MONTH;
            uint256 treasuryPercentage = (monthsAfterLock + 1) * 1000; // (months + 1) * 10%
            return treasuryPercentage > TOTAL_PERCENTAGE ? TOTAL_PERCENTAGE : treasuryPercentage;
        }
        
        if (_vestingType == VestingType.FOUNDERS) {
            // 3 months lock, then 10% monthly
            if (timeSinceListing < 3 * ONE_MONTH) return 0;
            uint256 monthsAfterLock = (timeSinceListing - 3 * ONE_MONTH) / ONE_MONTH;
            uint256 foundersPercentage = (monthsAfterLock + 1) * 1000; // (months + 1) * 10%
            return foundersPercentage > TOTAL_PERCENTAGE ? TOTAL_PERCENTAGE : foundersPercentage;
        }
        
        // Default for SEED_ROUND, PRIVATE_ROUND, REWARDS, REFERRALS_STAKING, ADVISORS, TEAM
        // 2.5% at 30d, 5% at 60d, 10% at 90d, then 10% monthly
        if (months == 0) return 0; // No tokens before 30 days
        if (months == 1) return 250; // 2.5%
        if (months == 2) return 750; // 2.5% + 5% = 7.5%
        if (months == 3) return 1750; // 2.5% + 5% + 10% = 17.5%
        
        // After 90 days: 17.5% + (additional months * 10%)
        uint256 additionalMonths = months - 3;
        uint256 totalPercentage = 1750 + (additionalMonths * 1000); // 17.5% + (additional months * 10%)
        return totalPercentage > TOTAL_PERCENTAGE ? TOTAL_PERCENTAGE : totalPercentage;
    }

    function withdraw() public onlyShareholder {
        uint256 allowedAmount = calculateAllowedAmount(msg.sender);
        uint256 withdrawnTokens = shareholders[msg.sender].withdrawnTokens;
        require(allowedAmount > withdrawnTokens, "No tokens available for withdrawal");
        
        StaxToken staxToken = StaxToken(staxTokenAddress);
        uint256 amount = allowedAmount - withdrawnTokens;
        require(amount > 0, "No tokens available for withdrawal");
        staxToken.transfer(msg.sender, amount);
        shareholders[msg.sender].withdrawnTokens += amount;
    }

    function addShareholder(
        address account, 
        uint256 maximumTokens
    ) public onlyOwner {
        if (shareholders[account].maximumTokens > 0) {
            shareholders[account].maximumTokens += maximumTokens;
        } else {
            shareholders[account] = ShareholderInfo(maximumTokens, 0);
        }
    }

    function getVestingInfo(address shareholderAddress) 
        public 
        view 
        returns (
            uint256 maximumTokens,
            uint256 withdrawnTokens,
            VestingType contractVestingType,
            uint256 availableForWithdrawal
        ) 
    {
        ShareholderInfo memory shareholder = shareholders[shareholderAddress];
        maximumTokens = shareholder.maximumTokens;
        withdrawnTokens = shareholder.withdrawnTokens;
        contractVestingType = vestingType;
        availableForWithdrawal = calculateAllowedAmount(shareholderAddress) - withdrawnTokens;
    }

    modifier onlyShareholder() {
        require(
            shareholders[msg.sender].maximumTokens > 0,
            "Only shareholder can call"
        );
        _;
    }
}
AggregatorV3Interface.sol 19 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

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

  function version() external view returns (uint256);

  function getRoundData(
    uint80 _roundId
  ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);

  function latestRoundData()
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
Ownable.sol 100 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

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

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

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
draft-IERC6093.sol 161 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
ERC20.sol 305 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both values are immutable: they can only be set once during construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /// @inheritdoc IERC20
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /// @inheritdoc IERC20
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /// @inheritdoc IERC20
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @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);
}
IERC20Metadata.sol 26 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity >=0.6.2;

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

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
convertUsdtToEth 0xeeb6d2dd → uint256
convertUsdtToShib 0xcbf4e425 → uint256
decimals 0x313ce567 → uint8
getEthPriceInUSDT 0x5faef62b → uint256
getShibPriceInEth 0x930928ab → uint256
maxSupply 0xd5abeb01 → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
privateListingEndTime 0x95c2b760 → uint256
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
usdtPrice 0xe136f65f → uint256
vestingGroups 0x236769d5 → address

Write Contract 14 functions

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

addGroup 0x7a642c51
address[] shareholderAddresses
uint256[] shareholderMaxAmount
uint8 vestingType
addShareholder 0x1cf0970a
address vestingGroupAddress
address account
uint256 amount
airdrop 0x8ba4cc3c
address to
uint256 amount
approve 0x095ea7b3
address spender
uint256 value
returns: bool
changePrice 0xa2b40d19
uint256 _price
endPrivateListing 0x203f9cdd
address treasuryVestingGroup
address account
mint 0xa0712d68
uint256 amount
mintForShib 0x46b8ec8a
uint256 amount
renounceOwnership 0x715018a6
No parameters
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
transferOwnership 0xf2fde38b
address newOwner
withdraw 0x3ccfd60b
No parameters
withdrawShib 0x609af8ca
No parameters

Recent Transactions

No transactions found for this address