Address Contract Partially Verified
Address
0x1c74d8C8FE37B0fA47deBc82E0AB6925A3DC4a2F
Balance
0 ETH
Nonce
1
Code Size
10303 bytes
Creator
0x00AFB5Ad...97C4 at tx 0x626731aa...7115b6
Indexed Transactions
0
Contract Bytecode
10303 bytes
0x6080604052600436106102305760003560e01c8063871c42b71161012e578063c5be2bc7116100ab578063e2ce1ac71161006f578063e2ce1ac7146106e1578063ec28438a146106f7578063f2fde38b1461070a578063f36aa6071461072a578063ff0087761461073d57600080fd5b8063c5be2bc71461058f578063c6af580b146105bf578063dd62ed3e146105d2578063dfa8bbeb14610618578063e06174e41461064857600080fd5b8063960bfe04116100f2578063960bfe0414610506578063a614ff7514610519578063a9059cbb1461052c578063b17b658d1461054c578063b9a6672c1461057c57600080fd5b8063871c42b71461047a5780638da5cb5b146104aa5780638fbf1e93146104c8578063918f8674146104db57806395d89b41146104f157600080fd5b80632febd2ae116101bc578063541958ff11610180578063541958ff146103f65780635afde063146104095780636cec0ceb1461041c57806370a082311461042f578063715018a61461046557600080fd5b80632febd2ae1461037f578063313ce5671461039257806339a91a15146103ae5780633d3d1141146103b65780634ff0b1d2146103c957600080fd5b80631f6976a6116102035780631f6976a6146102df57806323b872dd1461031757806327a14fc21461033757806327bf24e21461034c5780632b06dbbb1461035f57600080fd5b806306fdde0314610235578063095ea7b31461026057806318160ddd14610290578063181b72aa146102af575b600080fd5b34801561024157600080fd5b5061024a61076d565b60405161025791906120aa565b60405180910390f35b34801561026c57600080fd5b5061028061027b3660046120e2565b6107ff565b6040519015158152602001610257565b34801561029c57600080fd5b506002545b604051908152602001610257565b3480156102bb57600080fd5b506102806102ca36600461210e565b60126020526000908152604090205460ff1681565b3480156102eb57600080fd5b506019546102ff906001600160a01b031681565b6040516001600160a01b039091168152602001610257565b34801561032357600080fd5b5061028061033236600461212b565b610819565b61034a61034536600461216c565b610881565b005b61034a61035a36600461216c565b6108e8565b34801561036b57600080fd5b506102ff61037a36600461216c565b610925565b61034a61038d36600461219e565b61094f565b34801561039e57600080fd5b5060405160128152602001610257565b61034a6109e2565b61034a6103c436600461219e565b6109f4565b3480156103d557600080fd5b506102a16103e436600461210e565b60176020526000908152604090205481565b61034a6104043660046121d7565b610a58565b61034a61041736600461219e565b610aa9565b61034a61042a36600461216c565b610b0d565b34801561043b57600080fd5b506102a161044a36600461210e565b6001600160a01b031660009081526020819052604090205490565b34801561047157600080fd5b5061034a610b4a565b34801561048657600080fd5b5061028061049536600461210e565b60136020526000908152604090205460ff1681565b3480156104b657600080fd5b506005546001600160a01b03166102ff565b61034a6104d636600461210e565b610b5c565b3480156104e757600080fd5b506102a160105481565b3480156104fd57600080fd5b5061024a610bd9565b61034a61051436600461216c565b610be8565b61034a6105273660046121d7565b610c25565b34801561053857600080fd5b506102806105473660046120e2565b610c78565b34801561055857600080fd5b5061028061056736600461210e565b60156020526000908152604090205460ff1681565b61034a61058a36600461219e565b610cce565b34801561059b57600080fd5b506105af6105aa36600461216c565b610d32565b60405161025794939291906121f4565b61034a6105cd3660046121d7565b610e2d565b3480156105de57600080fd5b506102a16105ed366004612243565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b34801561062457600080fd5b5061028061063336600461210e565b60146020526000908152604090205460ff1681565b34801561065457600080fd5b50600854600954600a54600b54600c54600d54600e54600f54610691979695949392919060ff80821691610100810482169162010000909104168a565b604080519a8b5260208b0199909952978901969096526060880194909452608087019290925260a086015260c0850152151560e08401521515610100830152151561012082015261014001610257565b3480156106ed57600080fd5b506102a160075481565b61034a61070536600461216c565b610e76565b34801561071657600080fd5b5061034a61072536600461210e565b610ed6565b61034a610738366004612271565b610f19565b34801561074957600080fd5b5061028061075836600461210e565b60166020526000908152604090205460ff1681565b60606003805461077c906122f7565b80601f01602080910402602001604051908101604052809291908181526020018280546107a8906122f7565b80156107f55780601f106107ca576101008083540402835291602001916107f5565b820191906000526020600020905b8154815290600101906020018083116107d857829003601f168201915b5050505050905090565b60003361080d818585611119565b60019150505b92915050565b60003361082785828561112b565b60115460009060ff1660010361085f576011805460ff1916600217905561084f8686866111a9565b6011805460ff1916600117905590505b610873868661086e8488612347565b6118b9565b6001925050505b9392505050565b610889611918565b600e548110156108ac576040516307f02b7960e51b815260040160405180910390fd5b600d8190556040518181527f0176e9211818debdc4483c2bb0972798b7eb106239c8e465d4f1cee4ce5ae6e7906020015b60405180910390a150565b6108f0611918565b60098190556040518181527f933cdf8eb45e2bf17bff01bdf25b6516f3e3eda7bb81120c41bff9285008dac0906020016108dd565b6018818154811061093557600080fd5b6000918252602090912001546001600160a01b0316905081565b610957611918565b6001600160a01b03821661097e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038216600081815260156020908152604091829020805460ff19168515159081179091558251938452908301527f8b4bb68e253154bb2e75802b8914dddd9ecfaa965eca8e5a323553017b6bcc0d91015b60405180910390a15050565b6109ea611918565b6109f2611945565b565b6109fc611918565b6001600160a01b038216600081815260136020908152604091829020805460ff19168515159081179091558251938452908301527ff06306d03b4f240d8198e91f68418777423bb61df08b8d71032a9cfa211b4ae191016109d6565b610a60611918565b600f80548215156101000261ff00199091161790556040517ff65dac9e0e14b7aec57d4f1fea4ffce1fa2e22a81d90693329df834fbabbb789906108dd90831515815260200190565b610ab1611918565b6001600160a01b038216600081815260126020908152604091829020805460ff19168515159081179091558251938452908301527f8f3675e5a31b083483e5a782db4130316da1e3c5fca72fc2398f59692286d8a591016109d6565b610b15611918565b60108190556040518181527f4082bc252f347d223f4e804c3c4e90818ad544b959ffa807149351ad158bf016906020016108dd565b610b52611918565b6109f26000611c1b565b610b64611918565b6001600160a01b038116610b8b5760405163d92e233d60e01b815260040160405180910390fd5b601980546001600160a01b0319166001600160a01b0383169081179091556040519081527ff02c250c2f604285964f748fa097cd5c7fbf0bbd759efc47e3cc8851c4bfd89b906020016108dd565b60606004805461077c906122f7565b610bf0611918565b60088190556040518181527f46e8115bf463f9c29a9424fe152addef1bfaf2b43180d19bb7c2c78cc0ff1ebf906020016108dd565b610c2d611918565b600f8054821515620100000262ff0000199091161790556040517fa90851d18400a589974d1c5356d645068ab372fc9d53ed5f382f9209e8a504a7906108dd90831515815260200190565b6011546000903390829060ff16600103610cb4576011805460ff19166002179055610ca48286866111a9565b6011805460ff1916600117905590505b610cc3828661086e8488612347565b506001949350505050565b610cd6611918565b6001600160a01b038216600081815260146020908152604091829020805460ff19168515159081179091558251938452908301527f2a57b1eacb5962c472bd7a96baec43231b4ecc3ba3cffd4abf8186734102312d91016109d6565b60068181548110610d4257600080fd5b9060005260206000209060050201600091509050806000018054610d65906122f7565b80601f0160208091040260200160405190810160405280929190818152602001828054610d91906122f7565b8015610dde5780601f10610db357610100808354040283529160200191610dde565b820191906000526020600020905b815481529060010190602001808311610dc157829003601f168201915b50506040805160608101825260018701548152600287015460208201526003870154918101919091526004909501549394936001600160a01b0381169350600160a01b900460ff169150859050565b610e35611918565b600f805460ff19168215159081179091556040519081527fa3da88a45043f093f32d7cb1b95474f4f2ff653758ad43d6e512872081307fc0906020016108dd565b610e7e611918565b600c54811015610ea157604051635672035f60e11b815260040160405180910390fd5b600b8190556040518181527f4a02caf9e7317d663463d3d976767ba90289279dd55c0a46f962536efc87a9a6906020016108dd565b610ede611918565b6001600160a01b038116610f0d57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b610f1681611c1b565b50565b610f21611918565b8015610f2f57610f2f611945565b610f3b60066000611f8e565b60008080805b85811015611095576000878783818110610f5d57610f5d61235a565b9050602002810190610f6f9190612370565b610f809060a081019060800161210e565b6001600160a01b031603610fa75760405163a79afef960e01b815260040160405180910390fd5b6006878783818110610fbb57610fbb61235a565b9050602002810190610fcd9190612370565b815460018101835560009283526020909220909160050201610fef8282612410565b50508686828181106110035761100361235a565b90506020028101906110159190612370565b611023906020013585612574565b93508686828181106110375761103761235a565b90506020028101906110499190612370565b611057906040013584612574565b925086868281811061106b5761106b61235a565b905060200281019061107d9190612370565b61108b906060013583612574565b9150600101610f41565b506007859055600a548311806110ac5750600a5482115b806110b85750600a5481115b156110d657604051630b323bcb60e11b815260040160405180910390fd5b7fe8831bf32b04c19859d9916dbd57a89d041caf02ab126d86dc4edbbdb8fff57086868660405161110993929190612587565b60405180910390a1505050505050565b6111268383836001611c6d565b505050565b6001600160a01b0383811660009081526001602090815260408083209386168352929052205460001981146111a3578181101561119457604051637dc7a0d960e11b81526001600160a01b03841660048201526024810182905260448101839052606401610f04565b6111a384848484036000611c6d565b50505050565b6001600160a01b03831660009081526015602052604081205481908190819060ff16156111d557600192505b6001600160a01b03861660009081526015602052604090205460ff16156111fb57600191505b82158015611207575081155b15611210575060015b61121d8787878686611d42565b6112278686611dda565b82801561124c57506001600160a01b03861660009081526012602052604090205460ff165b1561125d576000935050505061087a565b81801561128257506001600160a01b03871660009081526012602052604090205460ff165b15611293576000935050505061087a565b80156112e9576001600160a01b03871660009081526012602052604090205460ff16806112d857506001600160a01b03861660009081526012602052604090205460ff165b156112e9576000935050505061087a565b600f5460ff166112ff576000935050505061087a565b6019546001600160a01b0390811690881681148061132e5750806001600160a01b0316876001600160a01b0316145b1561134057600094505050505061087a565b600654600090156118ad5760005b60065460ff8216101561186d57600086156113e157600060068360ff168154811061137b5761137b61235a565b90600052602060002090600502016001016000015411156113dc5760105460068360ff16815481106113af576113af61235a565b9060005260206000209060050201600101600001548a6113cf91906126b6565b6113d991906126cd565b90505b6114d2565b851561145357600060068360ff16815481106113ff576113ff61235a565b90600052602060002090600502016001016001015411156113dc5760105460068360ff16815481106114335761143361235a565b9060005260206000209060050201600101600101548a6113cf91906126b6565b84156114d257600060068360ff16815481106114715761147161235a565b90600052602060002090600502016001016002015411156114d25760105460068360ff16815481106114a5576114a561235a565b9060005260206000209060050201600101600201548a6114c591906126b6565b6114cf91906126cd565b90505b6114dc8184612574565b9250801561185c5760068260ff16815481106114fa576114fa61235a565b906000526020600020906005020160040160149054906101000a900460ff166116425761155a8b60068460ff16815481106115375761153761235a565b60009182526020909120600460059092020101546001600160a01b031683611e64565b60068260ff16815481106115705761157061235a565b906000526020600020906005020160040160009054906101000a90046001600160a01b03166001600160a01b03168b6001600160a01b03167f897726b6cfaff25a3bddca812f59ae0ed3a3d07ef84476ccd17cdefbffe10e11838a8a8a60068960ff16815481106115e3576115e361235a565b906000526020600020906005020160040160149054906101000a900460ff1660405161163595949392919094855292151560208501529015156040840152151560608301521515608082015260a00190565b60405180910390a361185c565b806017600060068560ff168154811061165d5761165d61235a565b60009182526020808320600460059093020191909101546001600160a01b031683528201929092526040018120805490919061169a908490612574565b925050819055506016600060068460ff16815481106116bb576116bb61235a565b60009182526020808320600460059093020191909101546001600160a01b0316835282019290925260400190205460ff166117a757601860068360ff16815481106117085761170861235a565b600091825260208083206004600590930201919091015483546001818101865594845291832090910180546001600160a01b0319166001600160a01b0390921691909117905560068054601692919060ff871690811061176a5761176a61235a565b60009182526020808320600592909202909101600401546001600160a01b031683528201929092526040019020805460ff19169115159190911790555b6117b28b8583611e64565b836001600160a01b03168b6001600160a01b03167f897726b6cfaff25a3bddca812f59ae0ed3a3d07ef84476ccd17cdefbffe10e11838a8a8a60068960ff16815481106118015761180161235a565b906000526020600020906005020160040160149054906101000a900460ff1660405161185395949392919094855292151560208501529015156040840152151560608301521515608082015260a00190565b60405180910390a35b50611866816126ef565b905061134e565b5083801561189457506008546001600160a01b038316600090815260208190526040902054115b156118a1576118a1611945565b945061087a9350505050565b50505050509392505050565b6001600160a01b0383166118e357604051634b637e8f60e11b815260006004820152602401610f04565b6001600160a01b03821661190d5760405163ec442f0560e01b815260006004820152602401610f04565b611126838383611e64565b6005546001600160a01b031633146109f25760405163118cdaa760e01b8152336004820152602401610f04565b6019546001600160a01b03166000818152602081905260409020548015611c175760185460009067ffffffffffffffff81111561198457611984612390565b6040519080825280602002602001820160405280156119ad578160200160208202803683370190505b50905060005b601854811015611b5c57600060176000601884815481106119d6576119d661235a565b60009182526020808320909101546001600160a01b0316835282019290925260400190205490508015611b53578360105482611a1291906126b6565b611a1c91906126cd565b838381518110611a2e57611a2e61235a565b60209081029190910101526009548411611ad55760006017600060188581548110611a5b57611a5b61235a565b60009182526020808320909101546001600160a01b0316835282019290925260400181209190915560188054601691839186908110611a9c57611a9c61235a565b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff1916911515919091179055611b53565b601054838381518110611aea57611aea61235a565b6020026020010151600860010154611b0291906126b6565b611b0c91906126cd565b611b169082612347565b6017600060188581548110611b2d57611b2d61235a565b60009182526020808320909101546001600160a01b031683528201929092526040019020555b506001016119b3565b506010546009546040516337a3292160e01b81526001600160a01b038616926337a3292192611b949230926018928892600401612789565b600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b505050507f70abc2c671179db962e066fe2d431f30e93e030d932704e9acd8fd566486103782601883604051611bfa939291906127d4565b60405180910390a160095482116111265761112660186000611faf565b5050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b038416611c975760405163e602df0560e01b815260006004820152602401610f04565b6001600160a01b038316611cc157604051634a1406b160e11b815260006004820152602401610f04565b6001600160a01b03808516600090815260016020908152604080832093871683529290522082905580156111a357826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611d3491815260200190565b60405180910390a350505050565b600f54610100900460ff1615611dd3578115611d79576001600160a01b03841660009081526014602052604090205460ff16611dd3575b8015611da0576001600160a01b03851660009081526014602052604090205460ff16611dd3575b80158015611dac575081155b611dd357600b54831115611dd3576040516329412db560e21b815260040160405180910390fd5b5050505050565b600f5462010000900460ff161515600003611df3575050565b6001600160a01b03821660009081526013602052604090205460ff1615611e18575050565b600d5481611e3b846001600160a01b031660009081526020819052604090205490565b611e459190612574565b1115611c175760405163fd42866160e01b815260040160405180910390fd5b6001600160a01b038316611e8f578060026000828254611e849190612574565b90915550611f019050565b6001600160a01b03831660009081526020819052604090205481811015611ee25760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401610f04565b6001600160a01b03841660009081526020819052604090209082900390555b6001600160a01b038216611f1d57600280548290039055611f3c565b6001600160a01b03821660009081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051611f8191815260200190565b60405180910390a3505050565b5080546000825560050290600052602060002090810190610f169190611fcd565b5080546000825590600052602060002090810190610f169190612015565b80821115612011576000611fe1828261202a565b506000600182018190556002820181905560038201556004810180546001600160a81b0319169055600501611fcd565b5090565b5b808211156120115760008155600101612016565b508054612036906122f7565b6000825580601f10612046575050565b601f016020900490600052602060002090810190610f169190612015565b6000815180845260005b8181101561208a5760208185018101518683018201520161206e565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061087a6020830184612064565b6001600160a01b0381168114610f1657600080fd5b80356120dd816120bd565b919050565b600080604083850312156120f557600080fd5b8235612100816120bd565b946020939093013593505050565b60006020828403121561212057600080fd5b813561087a816120bd565b60008060006060848603121561214057600080fd5b833561214b816120bd565b9250602084013561215b816120bd565b929592945050506040919091013590565b60006020828403121561217e57600080fd5b5035919050565b8015158114610f1657600080fd5b80356120dd81612185565b600080604083850312156121b157600080fd5b82356121bc816120bd565b915060208301356121cc81612185565b809150509250929050565b6000602082840312156121e957600080fd5b813561087a81612185565b60c08152600061220760c0830187612064565b905084516020830152602085015160408301526040850151606083015260018060a01b038416608083015282151560a083015295945050505050565b6000806040838503121561225657600080fd5b8235612261816120bd565b915060208301356121cc816120bd565b60008060006040848603121561228657600080fd5b833567ffffffffffffffff8082111561229e57600080fd5b818601915086601f8301126122b257600080fd5b8135818111156122c157600080fd5b8760208260051b85010111156122d657600080fd5b602092830195509350508401356122ec81612185565b809150509250925092565b600181811c9082168061230b57607f821691505b60208210810361232b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561081357610813612331565b634e487b7160e01b600052603260045260246000fd5b6000823560be1983360301811261238657600080fd5b9190910192915050565b634e487b7160e01b600052604160045260246000fd5b601f821115611126576000816000526020600020601f850160051c810160208610156123cf5750805b601f850160051c820191505b818110156123ee578281556001016123db565b505050505050565b60008135610813816120bd565b6000813561081381612185565b8135601e1983360301811261242457600080fd5b8201803567ffffffffffffffff81111561243d57600080fd5b6020813603818401131561245057600080fd5b6124648261245e86546122f7565b866123a6565b6000601f83116001811461249a576000841561248257508482018301355b600019600386901b1c1916600185901b1786556124f7565b600086815260209020601f19851690835b828110156124cc5787850186013582559385019360019091019085016124ab565b50858210156124eb5760001960f88760031b161c198585890101351681555b505060018460011b0186555b50508401803560018501556020810135600285015560400135600384015550506004810161254761252a608085016123f6565b82546001600160a01b0319166001600160a01b0391909116178255565b61112661255660a08501612403565b82805460ff60a01b191691151560a01b60ff60a01b16919091179055565b8082018082111561081357610813612331565b6040808252810183905260006060600585901b8301810190830186835b878110156126a157858403605f190183528135368a900360be190181126125ca57600080fd5b890160c0813536839003601e190181126125e357600080fd5b8201602081810191359067ffffffffffffffff82111561260257600080fd5b81360383131561261157600080fd5b83895281848a015260e093508183858b0137600084838b01015261264d818a018287018035825260208082013590830152604090810135910152565b6080925061265c8386016120d2565b6001600160a01b0381168a8501525060a0925061267a838601612193565b151592890192909252601f01601f19169096010194938401939290920191506001016125a4565b50505083151560208401529050949350505050565b808202811582820484141761081357610813612331565b6000826126ea57634e487b7160e01b600052601260045260246000fd5b500490565b600060ff821660ff810361270557612705612331565b60010192915050565b600081548084526020808501945083600052602060002060005b8381101561274d5781546001600160a01b031687529582019560019182019101612728565b509495945050505050565b60008151808452602080850194506020840160005b8381101561274d5781518752958201959082019060010161276d565b6001600160a01b038616815260a0602082018190526000906127ad9083018761270e565b82810360408401526127bf8187612758565b60608401959095525050608001529392505050565b8381526060602082015260006127ed606083018561270e565b82810360408401526127ff8185612758565b969550505050505056fea264697066735822122006bb97caa25271bd7b117332b16972e977b4647acac4e8f9f2000011e12897ab64736f6c63430008180033
Verified Source Code Partial Match
Compiler: v0.8.24+commit.e11b9ed9
EVM: paris
Optimization: Yes (200 runs)
Token.sol 1466 lines
// Sources flattened with hardhat v2.19.5 https://hardhat.org
// SPDX-License-Identifier: MIT
// File contracts/interfaces/IERC20.sol
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity 0.8.24;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// File contracts/interfaces/IERC20Metadata.sol
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity 0.8.24;
/**
* @dev Interface for the optional metadata functions from the ERC20 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);
}
// File contracts/interfaces/IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
// File contracts/interfaces/IUniswapV2Router02.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
// File contracts/interfaces/draft-IERC6093.sol
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity 0.8.24;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 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 ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-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 ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 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);
}
// File contracts/libraries/Context.sol
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity 0.8.24;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File contracts/libraries/ERC20.sol
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
pragma solidity 0.8.24;
/**
* @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 ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*/
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}.
*
* All two of these 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;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
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;
}
/**
* @dev See {IERC20-allowance}.
*/
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}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* 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:
* ```
* 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);
}
}
}
}
// File contracts/libraries/Ownable.sol
// Original license: SPDX_License_Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity 0.8.24;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File contracts/TaxHelper.sol
// Original license: SPDX_License_Identifier: MIT
pragma solidity 0.8.24;
/// @title TaxHelperUniswapV2
/// @author Boka
/// @notice Contract to convert tokens to ETH and divide among tax wallets using UniswapV2
/// @dev Can be used with multiple tokens
contract TaxHelperUniswapV2 is Ownable {
address public routerAddress;
mapping (address => bool) public approvedTokens;
event ApproveToken(address token, bool value);
event RouterAddressSet(address routerAddress);
event ConvertedToEth(address token, uint256 amount, address[] walletsWithTax, uint256[] percentages, uint256 DENOMINATOR, uint256 ethBalance);
event SentEth(address wallet, uint256 amount);
error TokenNotApproved(address sender);
error ZeroAddress();
constructor(address initialOwner, address _routerAddress)
Ownable(initialOwner)
{
setRouterAddress(_routerAddress);
}
/// @notice Approve a token to use this contract
/// @param token the token to approve
/// @param value true or false
function approveToken(address token, bool value) public onlyOwner {
approvedTokens[token] = value;
emit ApproveToken(token, value);
}
/// @notice Convert a token to ETH and divide among tax wallets
/// @dev only approve tokens or the owner may call this function
/// @param token the token to convert
/// @param walletsWithTax the wallets to divide the ETH among
/// @param percentages the percentages to divide the ETH among
/// @param DENOMINATOR the denominator to divide the percentages by
function convertToEthAndSend(address token, address[] memory walletsWithTax, uint256[] memory percentages, uint256 DENOMINATOR, uint256 maxThresholdSell) external {
if(!approvedTokens[msg.sender] && msg.sender != owner()) revert TokenNotApproved(msg.sender);
IERC20 tokenContract = IERC20(token);
uint256 balance = tokenContract.balanceOf(address(this));
if(balance > maxThresholdSell) {
balance = maxThresholdSell;
}
IUniswapV2Router02 uniswapRouter = IUniswapV2Router02(routerAddress);
tokenContract.approve(address(uniswapRouter), balance);
address[] memory path = new address[](2);
path[0] = token;
path[1] = uniswapRouter.WETH();
if(balance > 0) {
uniswapRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
balance,
0, // accept any amount of ETH
path,
address(this),
block.timestamp
);
uint256 ethBalance = address(this).balance;
emit ConvertedToEth(token, balance, walletsWithTax, percentages, DENOMINATOR, ethBalance);
for(uint256 i = 0; i < walletsWithTax.length; ++i) {
uint256 amountToSend = ethBalance * percentages[i] / DENOMINATOR;
payable(walletsWithTax[i]).transfer(amountToSend);
emit SentEth(walletsWithTax[i], amountToSend);
}
}
}
/// @notice Set the router address
/// @param _routerAddress the address of the UniswapV2Router02
function setRouterAddress(address _routerAddress) public onlyOwner {
if(_routerAddress == address(0)) revert ZeroAddress();
routerAddress = _routerAddress;
emit RouterAddressSet(_routerAddress);
}
/// @notice Withdraw the ETH from the contract
function withdraw() public onlyOwner {
payable(owner()).transfer(address(this).balance);
}
/// @notice Receive ETH
receive() payable external {
}
}
// File contracts/interfaces/ITaxHelper.sol
// Original license: SPDX_License_Identifier: MIT
pragma solidity 0.8.24;
interface ITaxHelper {
function convertToEthAndSend(address token, address[] memory walletsWithTax, uint256[] memory percentages, uint256 DENOMINATOR, uint256 maxThresholdSell) external;
}
// File contracts/Token.sol
// Original license: SPDX_License_Identifier: MIT
// Website: https://strike-protocol.com/
// Twitter: https://twitter.com/StrikeProtocol1
// TG: https://t.me/StrikeProtocol
pragma solidity 0.8.24;
/// @title Token
/// @author Boka
/// @notice ERC20 token with tax functionality
contract Token is ERC20, Ownable {
Tax[] public taxes;
uint256 public taxLength;
Settings public settings;
struct Settings {
uint256 threshold;
uint256 maxThresholdSell;
uint256 maxTax;
uint256 maxTxAmount;
uint256 minMaxTxAmount;
uint256 maxWalletAmount;
uint256 minMaxWalletAmount;
bool taxEnabled;
bool maxTxAmountEnabled;
bool maxWalletAmountEnabled;
}
struct Fee {
uint256 buy;
uint256 sell;
uint256 transfer;
}
struct Tax {
string name;
Fee fee;
address wallet;
bool withdrawAsGas;
}
uint256 public DENOMINATOR = 10000;
uint8 internal taxReentrancy = 1;
mapping (address => bool) public taxWhitelist;
mapping (address => bool) public maxWalletWhitelist;
mapping (address => bool) public maxTxWhitelist;
mapping (address => bool) public lpTokens;
mapping (address => bool) public taxesWithBalance;
mapping (address => uint256) public taxBalances;
address[] public walletsWithTax;
address public taxHelper;
event UpdatedTaxes(Tax[] _taxes, bool cleanWallets);
event TaxTransferred(address indexed sender, uint256 fee, address indexed wallet, bool isBuy, bool isSell, bool isTransfer, bool withdrawAsGas);
event TaxWithdrawn(uint256 amount, address[] walletsWithTax, uint256[] percentages);
event SetTaxHelper(address _taxHelper);
event SetDenominator(uint256 _denominator);
event SetTaxWhitelist(address _address, bool _value);
event SetLPToken(address _address, bool _value);
event SetTaxEnabled(bool _value);
event SetThreshold(uint256 _threshold);
event SetMaxTxAmount(uint256 _maxTxAmount);
event SetMaxWalletAmount(uint256 _maxWalletAmount);
event SetMaxWalletWhitelist(address _address, bool _value);
event SetMaxTxWhitelist(address _address, bool _value);
event SetMaxTxEnabled(bool _value);
event SetMaxWalletEnabled(bool _value);
event SetMaxThresholdSell(uint256 _maxThresholdSell);
error ExceedsMaxTax();
error ZeroAddressWallet();
error ZeroAddress();
error ExceedsMaxTxAmount();
error ExceedsMaxWalletAmount();
error UnderMinMaxTxAmount();
error UnderMinMaxWalletAmount();
constructor(
string memory name_,
string memory symbol_,
uint256 totalSupply_,
address initialOwner,
uint256 _maxTax,
uint256 _minMaxTxAmount,
uint256 _minMaxWalletAmount
) payable
ERC20(name_, symbol_)
Ownable(initialOwner)
{
_mint(initialOwner, totalSupply_);
settings.taxEnabled = false;
settings.maxTxAmountEnabled = false;
settings.maxWalletAmountEnabled = false;
settings.maxTax = _maxTax;
settings.minMaxTxAmount = _minMaxTxAmount;
settings.minMaxWalletAmount = _minMaxWalletAmount;
}
/// @notice enable the maximum transaction amount
/// @param _value true or false
function setMaxTxEnabled(bool _value) payable public onlyOwner {
settings.maxTxAmountEnabled = _value;
emit SetMaxTxEnabled(_value);
}
/// @notice enable the maximum wallet amount
/// @param _value true or false
function setMaxWalletEnabled(bool _value) payable public onlyOwner {
settings.maxWalletAmountEnabled = _value;
emit SetMaxWalletEnabled(_value);
}
/// @notice set the maximum transaction amount
/// @param _maxTxAmount the maximum transaction amount
function setMaxTxAmount(uint256 _maxTxAmount) payable public onlyOwner {
if(_maxTxAmount < settings.minMaxTxAmount) revert UnderMinMaxTxAmount();
settings.maxTxAmount = _maxTxAmount;
emit SetMaxTxAmount(_maxTxAmount);
}
/// @notice set the maximum wallet amount
/// @param _maxWalletAmount the maximum wallet amount
function setMaxWalletAmount(uint256 _maxWalletAmount) payable public onlyOwner {
if(_maxWalletAmount < settings.minMaxWalletAmount) revert UnderMinMaxWalletAmount();
settings.maxWalletAmount = _maxWalletAmount;
emit SetMaxWalletAmount(_maxWalletAmount);
}
/// @notice set the minimum balance to trigger the tax conversion
/// @param _threshold the minimum balance to trigger the tax conversion
function setThreshold(uint256 _threshold) payable public onlyOwner {
settings.threshold = _threshold;
emit SetThreshold(_threshold);
}
/// @notice set the maximum sell amount when the threshold is triggered to convert the tax
/// @param _maxThresholdSell the maximum sell amount
function setMaxThresholdSell(uint256 _maxThresholdSell) payable public onlyOwner {
settings.maxThresholdSell = _maxThresholdSell;
emit SetMaxThresholdSell(_maxThresholdSell);
}
/// @notice set the taxEnabled flag
/// @param _value sets the taxEnabled flag to true or false
function setTaxEnabled(bool _value) payable public onlyOwner {
settings.taxEnabled = _value;
emit SetTaxEnabled(_value);
}
/// @notice set the maxWalletWhitelist flag
/// @param _address the address to adjust the maxWalletWhitelist
/// @param _value true or false
function setMaxWalletWhitelist(address _address, bool _value) payable public onlyOwner {
maxWalletWhitelist[_address] = _value;
emit SetMaxWalletWhitelist(_address, _value);
}
/// @notice set the maxTxWhitelist flag
/// @param _address the address to adjust the maxTxWhitelist
/// @param _value true or false
function setMaxTxWhitelist(address _address, bool _value) payable public onlyOwner {
maxTxWhitelist[_address] = _value;
emit SetMaxTxWhitelist(_address, _value);
}
/// @notice set the taxWhitelist flag
/// @param _address the address to adjust the taxWhitelist
/// @param _value true or false
function setTaxWhitelist(address _address, bool _value) payable public onlyOwner {
taxWhitelist[_address] = _value;
emit SetTaxWhitelist(_address, _value);
}
/// @notice set whether an LP token is used to trigger the tax
/// @param _address the address of the LP token
/// @param _value true or false
function setLPToken(address _address, bool _value) payable public onlyOwner {
if(_address == address(0)) revert ZeroAddress();
lpTokens[_address] = _value;
emit SetLPToken(_address, _value);
}
/// @notice set the taxHelper address
/// @param _taxHelper the address of the taxHelper contract
function setTaxHelper(address _taxHelper) payable public onlyOwner {
if(_taxHelper == address(0)) revert ZeroAddress();
taxHelper = _taxHelper;
emit SetTaxHelper(_taxHelper);
}
/// @notice set the denominator to use for the tax calculation
/// @param _denominator the denominator to use for the tax calculation
function setDenominator(uint256 _denominator) payable public onlyOwner {
DENOMINATOR = _denominator;
emit SetDenominator(_denominator);
}
/// @notice update the taxes for the token
/// @dev if cleanWallets is true, the tax balances will be converted to ETH. This is useful if the taxes are updated and have different wallet addresses
/// @param _taxes the new taxes to apply
/// @param cleanWallets if true, the tax balances will be converted to ETH
function updateTaxes(Tax[] calldata _taxes, bool cleanWallets) payable public onlyOwner {
if(cleanWallets) {
_convertTaxToEth();
}
delete taxes;
uint256 totalTaxBuy;
uint256 totalTaxSell;
uint256 totalTaxTransfer;
for(uint i = 0; i < _taxes.length; ++i) {
if(_taxes[i].wallet == address(0)) revert ZeroAddressWallet();
taxes.push(_taxes[i]);
totalTaxBuy += _taxes[i].fee.buy;
totalTaxSell += _taxes[i].fee.sell;
totalTaxTransfer += _taxes[i].fee.transfer;
}
taxLength = _taxes.length;
if(totalTaxBuy > settings.maxTax || totalTaxSell > settings.maxTax || totalTaxTransfer > settings.maxTax) {
revert ExceedsMaxTax();
}
emit UpdatedTaxes(_taxes, cleanWallets);
}
/// @notice check the maximum transaction amount
/// @param from the address the tokens are being transferred from
/// @param to the address the tokens are being transferred to
/// @param value the amount of tokens being transferred
/// @param isBuy true if the transaction is a buy
/// @param isSell true if the transaction is a sell
function checkMaxTxAmount(address from, address to, uint256 value, bool isBuy, bool isSell) internal view {
if(settings.maxTxAmountEnabled == false) {
return;
}
if(isBuy) {
if(maxTxWhitelist[to]) {
return;
}
}
if(isSell) {
if(maxTxWhitelist[from]) {
return;
}
}
if(!isSell && !isBuy) {
return;
}
if(value > settings.maxTxAmount) {
revert ExceedsMaxTxAmount();
}
}
/// @notice check the maximum wallet amount
/// @param to the address the tokens are being transferred to
/// @param value the amount of tokens being transferred
function checkMaxWalletAmount(address to, uint256 value) internal view {
if(settings.maxWalletAmountEnabled == false) {
return;
}
if(maxWalletWhitelist[to]) {
return;
}
if(balanceOf(to) + value > settings.maxWalletAmount) {
revert ExceedsMaxWalletAmount();
}
}
/// @notice handle the tax for a transfer
/// @dev if the transaction is a sell, the tax will be converted to ETH if the taxHelper balance is above the threshold
/// @param from the address the tokens are being transferred from
/// @param to the address the tokens are being transferred to
/// @param value the amount of tokens being transferred
/// @return totalFeeAmount the total fee amount
function handleTax(address from, address to, uint256 value) internal returns (uint256) {
bool isBuy = false;
bool isSell = false;
bool isTransfer = false;
if(lpTokens[from]) {
isBuy = true;
}
if(lpTokens[to]) {
isSell = true;
}
if(!isBuy && !isSell) {
isTransfer = true;
}
checkMaxTxAmount(from, to, value, isBuy, isSell);
checkMaxWalletAmount(to, value);
if(isBuy && taxWhitelist[to]) {
return 0;
}
if(isSell && taxWhitelist[from]) {
return 0;
}
if(isTransfer) {
if(taxWhitelist[from] || taxWhitelist[to]) {
return 0;
}
}
if(!settings.taxEnabled) {
return 0;
}
ITaxHelper TaxHelper = ITaxHelper(taxHelper);
if(from == address(TaxHelper) || to == address(TaxHelper)) {
return 0;
}
uint256 totalFeeAmount;
if(taxes.length > 0) {
for(uint8 i = 0; i < taxes.length; ++i) {
uint256 fee;
if(isBuy) {
if(taxes[i].fee.buy > 0) {
fee = value * taxes[i].fee.buy / DENOMINATOR;
}
} else if(isSell) {
if(taxes[i].fee.sell > 0) {
fee = value * taxes[i].fee.sell / DENOMINATOR;
}
} else if(isTransfer) {
if(taxes[i].fee.transfer > 0) {
fee = value * taxes[i].fee.transfer / DENOMINATOR;
}
}
totalFeeAmount += fee;
if(fee != 0) {
if(!taxes[i].withdrawAsGas) {
_update(from, taxes[i].wallet, fee);
emit TaxTransferred(from, fee, taxes[i].wallet, isBuy, isSell, isTransfer, taxes[i].withdrawAsGas);
} else {
taxBalances[taxes[i].wallet] += fee;
if(!taxesWithBalance[taxes[i].wallet]) {
walletsWithTax.push(taxes[i].wallet);
taxesWithBalance[taxes[i].wallet] = true;
}
_update(from, address(TaxHelper), fee);
emit TaxTransferred(from, fee, address(TaxHelper), isBuy, isSell, isTransfer, taxes[i].withdrawAsGas);
}
}
}
if(isSell && balanceOf(address(TaxHelper)) > settings.threshold ){
_convertTaxToEth();
}
return totalFeeAmount;
}
}
/// @notice convert the tax balances to ETH
/// @dev this is a manual function call to be used to convert the tax balances to ETH if necessary
function convertTaxToEth() payable public onlyOwner {
_convertTaxToEth();
}
/// @notice convert the tax balances to ETH
function _convertTaxToEth() internal {
ITaxHelper TaxHelper = ITaxHelper(taxHelper);
// calculate percentages from taxHelper balance for each tax wallet
uint256 totalBalance = balanceOf(address(TaxHelper));
if(totalBalance > 0) {
uint256[] memory percentages = new uint256[](walletsWithTax.length);
for(uint i = 0; i < walletsWithTax.length; ++i) {
// calculate percentage of totalBalance for each wallet
uint256 balance = taxBalances[walletsWithTax[i]];
if(balance > 0) {
percentages[i] = balance * DENOMINATOR / totalBalance;
if(totalBalance <= settings.maxThresholdSell) {
taxBalances[walletsWithTax[i]] = 0;
taxesWithBalance[walletsWithTax[i]] = f...
// [truncated — 54457 bytes total]
Read Contract
DENOMINATOR 0x918f8674 → uint256
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
decimals 0x313ce567 → uint8
lpTokens 0xb17b658d → bool
maxTxWhitelist 0xdfa8bbeb → bool
maxWalletWhitelist 0x871c42b7 → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
settings 0xe06174e4 → uint256, uint256, uint256, uint256, uint256, uint256, uint256, bool, bool, bool
symbol 0x95d89b41 → string
taxBalances 0x4ff0b1d2 → uint256
taxHelper 0x1f6976a6 → address
taxLength 0xe2ce1ac7 → uint256
taxWhitelist 0x181b72aa → bool
taxes 0xc5be2bc7 → string, tuple, address, bool
taxesWithBalance 0xff008776 → bool
totalSupply 0x18160ddd → uint256
walletsWithTax 0x2b06dbbb → address
Write Contract 20 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address spender
uint256 value
returns: bool
convertTaxToEth 0x39a91a15
No parameters
renounceOwnership 0x715018a6
No parameters
setDenominator 0x6cec0ceb
uint256 _denominator
setLPToken 0x2febd2ae
address _address
bool _value
setMaxThresholdSell 0x27bf24e2
uint256 _maxThresholdSell
setMaxTxAmount 0xec28438a
uint256 _maxTxAmount
setMaxTxEnabled 0x541958ff
bool _value
setMaxTxWhitelist 0xb9a6672c
address _address
bool _value
setMaxWalletAmount 0x27a14fc2
uint256 _maxWalletAmount
setMaxWalletEnabled 0xa614ff75
bool _value
setMaxWalletWhitelist 0x3d3d1141
address _address
bool _value
setTaxEnabled 0xc6af580b
bool _value
setTaxHelper 0x8fbf1e93
address _taxHelper
setTaxWhitelist 0x5afde063
address _address
bool _value
setThreshold 0x960bfe04
uint256 _threshold
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
transferOwnership 0xf2fde38b
address newOwner
updateTaxes 0x258ab864
tuple[] _taxes
bool cleanWallets
Recent Transactions
No transactions found for this address