Address Contract Verified
Address
0xB3258E912B88781892489eDb8633C063e5F32cc5
Balance
0 ETH
Nonce
1
Code Size
22307 bytes
Creator
0xc0662111...BfF3 at tx 0x924f3004...fe94cb
Indexed Transactions
0
Contract Bytecode
22307 bytes
0x608060405234801561000f575f80fd5b5060043610610393575f3560e01c80637882bd33116101df578063ad7a672f11610109578063d664c0c8116100a9578063f073914711610079578063f0739147146108f2578063f2fde38b146108fa578063fa50c7d01461090d578063fbcbc0f11461092c575f80fd5b8063d664c0c81461085d578063d7b6453f14610890578063d9b26a69146108cc578063dae97c1b146108df575f80fd5b8063ca5b7465116100e4578063ca5b746514610801578063cb43b2dd1461080a578063d5cb06c41461081d578063d5eb911314610855575f80fd5b8063ad7a672f146107bc578063b8522043146107c5578063c54e44eb146107da575f80fd5b806394463e981161017f578063aa5f7e261161014f578063aa5f7e261461073b578063aafd847a1461074e578063ab6ddfa814610776578063ad5c464814610795575f80fd5b806394463e9814610664578063a87430ba14610677578063a8b9d24014610720578063a9c66b1414610733575f80fd5b806385a6b3ae116101ba57806385a6b3ae1461062e578063872b26da146106375780638da5cb5b1461064057806391b89fba14610651575f80fd5b80637882bd33146105ff5780637be1ee9714610612578063814eaeea1461061b575f80fd5b806345d05c42116102c05780636843cd8411610260578063715018a611610230578063715018a6146105c957806371778e7d146105d157806371a0f50e146105d95780637231c394146105ec575f80fd5b80636843cd84146105445780636a4740021461056c5780636f77926b1461057457806370a0823114610598575f80fd5b8063514d8a171161029b578063514d8a17146104ee57806351a8ea6314610515578063583a6c34146105285780635ad31e9914610531575f80fd5b806345d05c42146104d557806348c54b9d146104de5780634e71d92d146104e6575f80fd5b806327ce01471161033657806330bb4cff1161030657806330bb4cff14610494578063315a095d1461049c57806337b90a4f146104af5780633865d2b5146104c2575f80fd5b806327ce0147146104475780632b2e0d5d1461045a5780632d141467146104775780632e29490d1461047f575f80fd5b806317460b1b1161037157806317460b1b146104065780631a2c2e861461040e5780631b90e0e8146104215780631d5d7cc914610434575f80fd5b80630758d9241461039757806308f2f233146103db5780630fc924e3146103fc575b5f80fd5b6103be7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b6040516001600160a01b0390911681526020015b60405180910390f35b6103ee6103e9366004614d7a565b610969565b6040519081526020016103d2565b610404610b3b565b005b610404610c1e565b61040461041c366004614d93565b610c60565b61040461042f366004614d93565b610c97565b610404610442366004614dc2565b610d34565b6103ee610455366004614d7a565b611338565b6010546104679060ff1681565b60405190151581526020016103d2565b6103ee61139a565b6104876113d7565b6040516103d29190614ddd565b6006546103ee565b6104046104aa366004614d93565b6113e3565b6104046104bd366004614e34565b61188d565b6103ee6104d0366004614d93565b611ea1565b6103ee600c5481565b610404612066565b61040461235b565b6103be7f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e781565b610404610523366004614f37565b61242a565b6103ee600b5481565b61040461053f366004615073565b61265c565b6103ee610552366004614d7a565b6001600160a01b03165f9081526004602052604090205490565b6104046127e5565b610587610582366004614d7a565b6127f1565b6040516103d295949392919061516c565b6103ee6105a6366004614d7a565b6001600160a01b03165f908152601160205260409020546001600160701b031690565b6104046128c2565b6005546103ee565b6103ee6105e7366004614d7a565b612935565b6104046105fa3660046151fc565b612a0c565b61040461060d366004614d93565b612af9565b6103ee600e5481565b61040461062936600461522e565b612b86565b6103ee60065481565b6103ee600f5481565b6007546001600160a01b03166103be565b6103ee61065f366004614d7a565b612efa565b610404610672366004615247565b612f04565b6106d7610685366004614d7a565b60116020525f90815260409020805460018201546002909201546001600160701b0380831693600160701b909304169165ffffffffffff81169160ff600160301b8304811692600160381b9004169086565b604080516001600160701b03978816815296909516602087015265ffffffffffff909316938501939093521515606084015260ff909116608083015260a082015260c0016103d2565b6103ee61072e366004614d7a565b612f96565b610404612fbb565b610404610749366004614d93565b6130af565b6103ee61075c366004614d7a565b6001600160a01b03165f9081526003602052604090205490565b6103ee610784366004614d7a565b60046020525f908152604090205481565b6103be7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6103ee60055481565b6107cd6134c1565b6040516103d291906152aa565b6103be7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec781565b6103ee600d5481565b610404610818366004614d93565b6134cd565b6103ee61082b366004614d7a565b6001600160a01b03165f90815260116020526040902054600160701b90046001600160701b031690565b610404613673565b61087061086b366004614d7a565b61372f565b6040805194855260208501939093529183015260608201526080016103d2565b600f54600c54600d54600e5460105460ff166040805195865260208601949094529284019190915260608301521515608082015260a0016103d2565b6104046108da366004615247565b6137d1565b6104046108ed366004614d93565b613870565b6104046138f0565b610404610908366004614d7a565b6138fa565b6103ee61091b366004614d93565b600a6020525f908152604090205481565b61093f61093a366004614d7a565b61392d565b604080516001600160a01b03909516855260208501939093529183015260608201526080016103d2565b5f8061097483612f96565b604080516003808252608082019092529192505f9190602082016060803683370190505090507f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7815f815181106109cd576109cd6152bc565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110610a2157610a216152bc565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e781600281518110610a7557610a756152bc565b6001600160a01b03928316602091820292909201015260405163d06ca61f60e01b81525f917f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d169063d06ca61f90610ad390869086906004016152d0565b5f60405180830381865afa158015610aed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b1491908101906152e8565b905080600281518110610b2957610b296152bc565b60200260200101519350505050919050565b6007546001600160a01b03163314610b6e5760405162461bcd60e51b8152600401610b6590615379565b60405180910390fd5b60105460ff1615610bba5760405162461bcd60e51b81526020600482015260166024820152755265776172647320616c72656164792061637469766560501b6044820152606401610b65565b5f600c5411610c0b5760405162461bcd60e51b815260206004820152601e60248201527f5265776172647320706572207365636f6e64206d7573742062652073657400006044820152606401610b65565b42600d556010805460ff19166001179055565b6007546001600160a01b03163314610c485760405162461bcd60e51b8152600401610b6590615379565b610c50613969565b5f600c556010805460ff19169055565b6007546001600160a01b03163314610c8a5760405162461bcd60e51b8152600401610b6590615379565b610c92613969565b600c55565b6007546001600160a01b03163314610cc15760405162461bcd60e51b8152600401610b6590615379565b610ccc6008826139ca565b610d185760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e6720506572696f6420646f65736e2774206578697374000000006044820152606401610b65565b610d236008826139e4565b505f908152600a6020526040812055565b60025f5403610d555760405162461bcd60e51b8152600401610b65906153ae565b60025f55610d61613673565b335f908152601160209081526040808320815160c08101835281546001600160701b038082168352600160701b9091041693810193909352600181015465ffffffffffff81169284019290925260ff600160301b830481161580156060860152600160381b9093041660808401526002015460a0830152909190610e11576064826080015160ff16835f0151610df791906153f9565b610e01919061542f565b6001600160701b03169050610e38565b600b548251606491610e2b916001600160701b031661545c565b610e359190615473565b90505b81515f90610e509083906001600160701b0316615486565b83519091506001600160701b0316610eaa5760405162461bcd60e51b815260206004820152601760248201527f4e6f20746f6b656e7320776974682077697468647261770000000000000000006044820152606401610b65565b5f84158015610ec2575083516001600160701b031615155b1561101d57610ecf613969565b60a0840151600e54335f90815260046020526040902054610f0c9291610f069164e8d4a5100091610f0091906139ef565b90613a6d565b90613aae565b9050801561101d57600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015610f79573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f9d9190615499565b610fa79190615486565b811115610fc65760405162461bcd60e51b8152600401610b65906154b0565b610ffa6001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e7163383613aef565b60405181815233905f805160206156ce8339815191529060200160405180910390a25b835f01516001600160701b0316600f5f82825461103a9190615486565b90915550505f8085526040808601828152602080880184815260a08901858152338087526011909352948490208951815492516001600160701b03908116600160701b026001600160e01b0319909416911617919091178155915160018301805460608b015160808c015160ff16600160381b0260ff60381b19911515600160301b0266ffffffffffffff1990931665ffffffffffff9590951694909417919091171691909117905592516002909101555163a9059cbb60e01b81527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b03169163a9059cbb9161114a919086906004016001600160a01b03929092168252602082015260400190565b6020604051808303815f875af1158015611166573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061118a91906154e7565b508215611242577f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b031663a9059cbb6111d26007546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018690526044016020604051808303815f875af115801561121c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061124091906154e7565b505b61124c335f613b57565b6040516370a0823160e01b81523060048201527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa1580156112ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d29190615499565b6014556112e0601233613b6c565b156112f2576112f0601233613b8d565b505b604080518381526020810185905233917fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595910160405180910390a2505060015f55505050565b6001600160a01b0381165f908152600260209081526040808320546004909252822054600154600160801b9261138a926113859261137f9161137a91906139ef565b613ba1565b90613baf565b613be9565b6113949190615473565b92915050565b5f42600d5411806113ae575060105460ff16155b156113b857505f90565b600c54600d546113c89042615486565b6113d2919061545c565b905090565b60606113d26008613bfa565b60025f54036114045760405162461bcd60e51b8152600401610b65906153ae565b60025f55611410613673565b335f90815260116020908152604091829020825160c08101845281546001600160701b038082168352600160701b90910416928101839052600182015465ffffffffffff81169482019490945260ff600160301b8504811615156060830152600160381b90940490931660808401526002015460a08301524210156114c35760405162461bcd60e51b8152602060048201526009602482015268546f6f206561726c7960b81b6044820152606401610b65565b80516001600160701b031682111561152c5760405162461bcd60e51b815260206004820152602660248201527f52657175657374696e6720746f20776974686472617720746f6f206d616e7920604482015265746f6b656e7360d01b6064820152608401610b65565b5f611535613969565b60a0820151600e54335f908152600460205260409020546115669291610f069164e8d4a5100091610f0091906139ef565b9050801561167757600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa1580156115d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f79190615499565b6116019190615486565b8111156116205760405162461bcd60e51b8152600401610b65906154b0565b6116546001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e7163383613aef565b60405181815233905f805160206156ce8339815191529060200160405180910390a25b82600f5f8282546116889190615486565b909155505081518390839061169e908390615502565b6001600160701b03169052506116b43383613c06565b600e54335f908152600460205260409020546116da9164e8d4a5100091610f00916139ef565b60a08301908152335f8181526011602090815260409182902086518154928801516001600160701b03908116600160701b026001600160e01b031990941691161791909117815581860151600182018054606089015160808a015160ff16600160381b0260ff60381b19911515600160301b0266ffffffffffffff1990931665ffffffffffff9095169490941791909117169190911790559251600290930192909255905163a9059cbb60e01b81527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b03169163a9059cbb916117dd919087906004016001600160a01b03929092168252602082015260400190565b6020604051808303815f875af11580156117f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061181d91906154e7565b50611829601233613b6c565b801561183d575081516001600160701b0316155b1561184f5761184d601233613b8d565b505b60405183815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a2505060015f5550565b60025f54036118ae5760405162461bcd60e51b8152600401610b65906153ae565b60025f556118ba613673565b335f90815260116020908152604091829020825160c08101845281546001600160701b038082168352600160701b9091041692810192909252600181015465ffffffffffff81169383019390935260ff600160301b8404811615156060840152600160381b909304909216608082015260029091015460a0820152826119705760405162461bcd60e51b815260206004820152600b60248201526a16995c9bc8105b5bdd5b9d60aa1b6044820152606401610b65565b611983600865ffffffffffff84166139ca565b61199f5760405162461bcd60e51b8152600401610b6590615521565b8165ffffffffffff16816040015165ffffffffffff1611156119d35760405162461bcd60e51b8152600401610b6590615551565b6119de601233613b6c565b6119ef576119ed601233613ce3565b505b6119f7613969565b80516001600160701b031615611b4d5760a0810151600e54335f908152600460205260408120549092611a3a929091610f069164e8d4a5100091610f00916139ef565b90508015611b4b57600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015611aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611acb9190615499565b611ad59190615486565b811115611af45760405162461bcd60e51b8152600401610b65906154b0565b611b286001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e7163383613aef565b60405181815233905f805160206156ce8339815191529060200160405180910390a25b505b65ffffffffffff82166040820152611b68826201518061559a565b611b7a9065ffffffffffff16426155bb565b65ffffffffffff1660208201526040516370a0823160e01b81523060048201525f9081907f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015611bed573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c119190615499565b6040516323b872dd60e01b8152336004820152306024820152604481018790529091507f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906323b872dd906064016020604051808303815f875af1158015611c84573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ca891906154e7565b506040516370a0823160e01b81523060048201526001600160701b038216907f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015611d16573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d3a9190615499565b611d449190615486565b915081835f01818151611d5791906155ce565b6001600160701b0316905250611d6d3384613c06565b335f90815260046020526040812054600f805491926001600160701b03861692611d989084906155bb565b9091555050600e54611db69064e8d4a5100090610f009084906139ef565b60a08501526040516001600160701b038416815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a25050335f90815260116020908152604080832085518154938701516001600160701b03908116600160701b026001600160e01b0319909516911617929092178255840151600180830180546060880151608089015160ff16600160381b0260ff60381b19911515600160301b0266ffffffffffffff1990931665ffffffffffff9096169590951791909117169290921790915560a09094015160029091015591909155505050565b604080516003808252608082019092525f91829190602082016060803683370190505090507f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7815f81518110611ef957611ef96152bc565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110611f4d57611f4d6152bc565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e781600281518110611fa157611fa16152bc565b6001600160a01b03928316602091820292909201015260405163d06ca61f60e01b81525f917f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d169063d06ca61f90611fff90879086906004016152d0565b5f60405180830381865afa158015612019573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261204091908101906152e8565b905080600281518110612055576120556152bc565b602002602001015192505050919050565b60025f54036120875760405162461bcd60e51b8152600401610b65906153ae565b60025f55612093613673565b335f90815260116020908152604091829020825160c08101845281546001600160701b038082168352600160701b9091041692810192909252600181015465ffffffffffff81169383019390935260ff600160301b8404811615156060840152600160381b909304909216608082015260029091015460a0820152612116613969565b60a0810151600e54335f908152600460205260408120549092612149929091610f069164e8d4a5100091610f00916139ef565b9050801561225a57600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa1580156121b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121da9190615499565b6121e49190615486565b8111156122035760405162461bcd60e51b8152600401610b65906154b0565b6122376001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e7163383613aef565b60405181815233905f805160206156ce8339815191529060200160405180910390a25b600e54335f908152600460205260409020546122809164e8d4a5100091610f00916139ef565b60a083015260405181815233907f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d49060200160405180910390a250335f90815260116020908152604080832084518154938601516001600160701b03908116600160701b026001600160e01b0319909516911617929092178255830151600180830180546060870151608088015160ff16600160381b0260ff60381b19911515600160301b0266ffffffffffffff1990931665ffffffffffff9096169590951791909117169290921790915560a09093015160029091015555565b60025f540361237c5760405162461bcd60e51b8152600401610b65906153ae565b60025f55612388613673565b6040516370a0823160e01b81523060048201527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa1580156123ea573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061240e9190615499565b60145561241b335f613cf7565b50612424613969565b60015f55565b6007546001600160a01b031633146124545760405162461bcd60e51b8152600401610b6590615379565b5f5b8351811015612656575f848281518110612472576124726152bc565b6020908102919091018101516001600160a01b0381165f90815260118352604090819020815160c08101835281546001600160701b038082168352600160701b9091041694810194909452600181015465ffffffffffff81169285019290925260ff600160301b8304811615156060860152600160381b90920490911660808401526002015460a083015291508315612599575f858481518110612518576125186152bc565b6020026020010151905060648160ff1611156125855760405162461bcd60e51b815260206004820152602660248201527f43616e6e6f742073657420656d657267656e63792070656e616c7479206f766560448201526572203130302560d01b6064820152608401610b65565b6001606083015260ff1660808201526125a7565b5f6060820181905260808201525b6001600160a01b039091165f9081526011602090815260409182902083518154928501516001600160701b03908116600160701b026001600160e01b031990941691161791909117815590820151600180830180546060860151608087015160ff16600160381b0260ff60381b19911515600160301b0266ffffffffffffff1990931665ffffffffffff9096169590951791909117169290921790915560a09092015160029091015501612456565b50505050565b6007546001600160a01b031633146126865760405162461bcd60e51b8152600401610b6590615379565b5f61268f613969565b5f5b8451811015612728578381815181106126ac576126ac6152bc565b60200260200101516001600160701b0316826126c891906155bb565b91506127208582815181106126df576126df6152bc565b60200260200101518583815181106126f9576126f96152bc565b6020026020010151858481518110612713576127136152bc565b6020026020010151613d63565b600101612691565b507f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b03166323b872dd61276a6007546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064016020604051808303815f875af11580156127ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127de91906154e7565b5050505050565b6127ee33614186565b50565b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a081018290529080808061282e8661392d565b6001600160a01b039099165f90815260116020908152604091829020825160c08101845281546001600160701b038082168352600160701b9091041692810192909252600181015465ffffffffffff81169383019390935260ff600160301b8404811615156060840152600160381b909304909216608082015260029091015460a082015299929891975095509350915050565b6007546001600160a01b031633146128ec5760405162461bcd60e51b8152600401610b6590615379565b6007546040515f916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600780546001600160a01b0319169055565b6001600160a01b0381165f90815260116020526040812080546001600160701b0316820361296557505f92915050565b600e54600d544211801561297a575060055415155b156129cd575f600d544261298e9190615486565b90505f600c548261299f919061545c565b6005549091506129b48264e8d4a5100061545c565b6129be9190615473565b6129c890846155bb565b925050505b60028201546001600160a01b0385165f90815260046020526040902054612a049190610f069064e8d4a5100090610f0090866139ef565b949350505050565b6007546001600160a01b03163314612a365760405162461bcd60e51b8152600401610b6590615379565b5f5b8151811015612af5575f828281518110612a5457612a546152bc565b6020908102919091018101516001600160a01b0381165f90815260118352604090819020815160c08101835281546001600160701b038082168352600160701b9091041694810194909452600181015465ffffffffffff81169285019290925260ff600160301b8304811615156060860152600160381b90920490911660808401526002015460a08301529150612aeb8282613c06565b5050600101612a38565b5050565b5f8111612b485760405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606401610b65565b612b7d6001600160a01b037f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec71633308461424d565b6127ee81614285565b60025f5403612ba75760405162461bcd60e51b8152600401610b65906153ae565b60025f55612bb3613673565b335f90815260116020908152604091829020825160c08101845281546001600160701b038082168352600160701b9091041692810192909252600181015465ffffffffffff8082169484019490945260ff600160301b8204811615156060850152600160381b9091041660808301526002015460a082015290612c3a9060089084166139ca565b612c565760405162461bcd60e51b8152600401610b6590615521565b8165ffffffffffff16816040015165ffffffffffff161115612c8a5760405162461bcd60e51b8152600401610b6590615551565b612c92613969565b80516001600160701b031615612de85760a0810151600e54335f908152600460205260408120549092612cd5929091610f069164e8d4a5100091610f00916139ef565b90508015612de657600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015612d42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d669190615499565b612d709190615486565b811115612d8f5760405162461bcd60e51b8152600401610b65906154b0565b612dc36001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e7163383613aef565b60405181815233905f805160206156ce8339815191529060200160405180910390a25b505b65ffffffffffff82166040820152612e03826201518061559a565b612e159065ffffffffffff16426155bb565b65ffffffffffff166020820152612e2c3382613c06565b600e54335f90815260046020526040902054612e529164e8d4a5100091610f00916139ef565b60a08201908152335f90815260116020908152604080832085518154938701516001600160701b03908116600160701b026001600160e01b031990951691161792909217825584015160018083018054606088015160809098015160ff16600160381b0260ff60381b19981515600160301b0266ffffffffffffff1990921665ffffffffffff9095169490941717969096169190911790945591516002909201919091555550565b5f61139482612f96565b6007546001600160a01b03163314612f2e5760405162461bcd60e51b8152600401610b6590615379565b612f396008836139ca565b612f855760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e6720506572696f6420646f65736e2774206578697374000000006044820152606401610b65565b5f918252600a602052604090912055565b6001600160a01b0381165f9081526003602052604081205461139490610f0684611338565b6007546001600160a01b03163314612fe55760405162461bcd60e51b8152600401610b6590615379565b5f612fee6134c1565b90505f5b8151811015612af5575f82828151811061300e5761300e6152bc565b6020908102919091018101516001600160a01b0381165f90815260118352604090819020815160c08101835281546001600160701b038082168352600160701b9091041694810194909452600181015465ffffffffffff81169285019290925260ff600160301b8304811615156060860152600160381b90920490911660808401526002015460a083015291506130a58282613c06565b5050600101612ff2565b60025f54036130d05760405162461bcd60e51b8152600401610b65906153ae565b60025f556130dc613673565b335f818152601160205260408120916130f49061430d565b90508015613289576040516370a0823160e01b81523060048201525f907f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015613160573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131849190615499565b9050613190828561439e565b6040516370a0823160e01b81523060048201525f9082906001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e716906370a0823190602401602060405180830381865afa1580156131f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061321a9190615499565b6132249190615486565b8454909150819085905f906132439084906001600160701b03166155ce565b92506101000a8154816001600160701b0302191690836001600160701b03160217905550806001600160701b0316600f5f82825461328191906155bb565b909155505050505b60105460ff1680156132a4575081546001600160701b031615155b15613417576132b1613969565b335f908152600460205260408120546002840154600e549192916132e69190610f069064e8d4a5100090610f009087906139ef565b9050801561341457600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015613353573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133779190615499565b6133819190615486565b8111156133a05760405162461bcd60e51b8152600401610b65906154b0565b83546133b69082906001600160701b03166155bb565b84546dffffffffffffffffffffffffffff19166001600160701b0391909116178455600f80548291905f906133ec9084906155bb565b909155505060405181815233905f805160206156ce8339815191529060200160405180910390a25b50505b6040805160c08101825283546001600160701b038082168352600160701b909104166020820152600184015465ffffffffffff81169282019290925260ff600160301b8304811615156060830152600160381b9092049091166080820152600283015460a082015261348a903390613c06565b600e54335f908152600460205260409020546134b09164e8d4a5100091610f00916139ef565b600290920191909155505060015f55565b60606113d26012613bfa565b6007546001600160a01b031633146134f75760405162461bcd60e51b8152600401610b6590615379565b600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa15801561355c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135809190615499565b61358a9190615486565b8111156135e55760405162461bcd60e51b815260206004820152602360248201527f43616e6e6f74207769746864726177206d6f7265207468616e20617661696c61604482015262626c6560e81b6064820152608401610b65565b60405163a9059cbb60e01b8152336004820152602481018290527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b03169063a9059cbb906044016020604051808303815f875af115801561364f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612af591906154e7565b6040516370a0823160e01b81523060048201525f907f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa1580156136d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136fb9190615499565b905060145481116137095750565b5f601454826137189190615486565b90508015612af55761372981614285565b50601455565b6001600160a01b0381165f818152601160205260408082208054600282015492516338d07a8760e11b815260048101959095526001600160701b03808216959394600160701b909204169290919030906371a0f50e90602401602060405180830381865afa1580156137a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906137c79190615499565b9150509193509193565b6007546001600160a01b031633146137fb5760405162461bcd60e51b8152600401610b6590615379565b6138066008836139ca565b156138535760405162461bcd60e51b815260206004820152601c60248201527f5374616b696e6720506572696f6420616c7265616479206164646564000000006044820152606401610b65565b61385e600883614584565b505f918252600a602052604090912055565b6007546001600160a01b0316331461389a5760405162461bcd60e51b8152600401610b6590615379565b60328111156138eb5760405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742073657420686967686572207468616e203530250000000000006044820152606401610b65565b600b55565b6138f8613673565b565b6007546001600160a01b031633146139245760405162461bcd60e51b8152600401610b6590615379565b6127ee8161458f565b805f808061393a84612f96565b925061394584611338565b6001600160a01b0385165f9081526004602052604090205494969395509392915050565b600d54421161397457565b6005545f819003613986575042600d55565b5f61398f61139a565b9050805f036139a057505042600d55565b6139bf6139b683610f008464e8d4a510006139ef565b600e549061464f565b600e55505042600d55565b5f81815260018301602052604081205415155b9392505050565b5f6139dd83836146ad565b5f825f036139fe57505f611394565b5f613a09838561545c565b905082613a168583615473565b146139dd5760405162461bcd60e51b815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6044820152607760f81b6064820152608401610b65565b5f6139dd83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614797565b5f6139dd83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506147cc565b6040516001600160a01b038316602482015260448101829052613b5290849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526147fb565b505050565b613b6182826148cc565b613b52826001613cf7565b6001600160a01b0381165f90815260018301602052604081205415156139dd565b5f6139dd836001600160a01b0384166146ad565b5f8181811215611394575f80fd5b5f80613bbb83856155ed565b90505f8312158015613bcd5750838112155b80613be157505f83128015613be157508381125b6139dd575f80fd5b5f80821215613bf6575f80fd5b5090565b60605f6139dd83614960565b60408082015165ffffffffffff165f908152600a6020522054613c56908390606490613c3290826155bb565b8451613c4791906001600160701b031661545c565b613c519190615473565b613b57565b6040516370a0823160e01b81523060048201527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76001600160a01b0316906370a0823190602401602060405180830381865afa158015613cb8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cdc9190615499565b6014555050565b5f6139dd836001600160a01b0384166149b9565b5f80613d0284614186565b90508015613d5a57821515846001600160a01b03167fa2c38e2d2fb7e3e1912d937fd1ca11ed6d51864dee4cfa7a7bf02becd7acf09283604051613d4891815260200190565b60405180910390a36001915050611394565b505f9392505050565b6001600160a01b0383165f90815260116020908152604091829020825160c08101845281546001600160701b038082168352600160701b909104811693820193909352600182015465ffffffffffff81169482019490945260ff600160301b8504811615156060830152600160381b90940490931660808401526002015460a08301528316613e225760405162461bcd60e51b815260206004820152600b60248201526a16995c9bc8105b5bdd5b9d60aa1b6044820152606401610b65565b613e35600865ffffffffffff84166139ca565b613e515760405162461bcd60e51b8152600401610b6590615521565b613e5c601285613b6c565b613e6d57613e6b601285613ce3565b505b80516001600160701b031615613fda5760a0810151600e546001600160a01b0386165f908152600460205260408120549092613eb9929091610f069164e8d4a5100091610f00916139ef565b90508015613fd857600f546040516370a0823160e01b81523060048201527f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e76001600160a01b0316906370a0823190602401602060405180830381865afa158015613f26573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f4a9190615499565b613f549190615486565b811115613f735760405162461bcd60e51b8152600401610b65906154b0565b613fa76001600160a01b037f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e7168683613aef565b846001600160a01b03165f805160206156ce83398151915282604051613fcf91815260200190565b60405180910390a25b505b65ffffffffffff82166040820152613ff5826201518061559a565b6140079065ffffffffffff16426155bb565b65ffffffffffff1660208201528051839082906140259083906155ce565b6001600160701b031690525061403b8482613c06565b600e546001600160a01b0385165f9081526004602052604090205461406a9164e8d4a5100091610f00916139ef565b60a0820152600f80546001600160701b03851691905f9061408c9084906155bb565b90915550506040516001600160701b03841681526001600160a01b038516907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a26001600160a01b039093165f9081526011602090815260409182902085518154928701516001600160701b03908116600160701b026001600160e01b0319909416911617919091178155908401516001820180546060870151608088015160ff16600160381b0260ff60381b19911515600160301b0266ffffffffffffff1990931665ffffffffffff90951694909417919091171691909117905560a0909301516002909301929092555050565b5f8061419183612f96565b90508015614245576001600160a01b0383165f908152600360205260409020546141bb908261464f565b6001600160a01b0384165f81815260036020526040908190209290925590517fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d906142099084815260200190565b60405180910390a26113946001600160a01b037f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7168483613aef565b505f92915050565b6040516001600160a01b03808516602483015283166044820152606481018290526126569085906323b872dd60e01b90608401613b1b565b5f60055411801561429557505f81115b156127ee576005546142c2906142af83600160801b6139ef565b6142b99190615473565b6001549061464f565b60015560405181815233907fa493a9229478c3fcd73f66d2cdeb7f94fd0f341da924d1054236d784541165119060200160405180910390a2600654614307908261464f565b60065550565b5f61431782612f96565b90508015614399576001600160a01b0382165f908152600360205260409020546143429082906155bb565b6001600160a01b0383165f81815260036020526040908190209290925590517fee503bee2bb6a87e57bc57db795f98137327401a0e7b7ce42e37926cc1a9ca4d906143909084815260200190565b60405180910390a25b919050565b604080516003808252608082019092525f91602082016060803683370190505090507f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7815f815181106143f3576143f36152bc565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600181518110614447576144476152bc565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000382ec856c90ef7ed7c936852f6603568ce1984e78160028151811061449b5761449b6152bc565b6001600160a01b0392831660209182029290920101526144fe907f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7167f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d85614a05565b604051635c11d79560e01b81526001600160a01b037f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d1690635c11d795906145529086908690869030904290600401615614565b5f604051808303815f87803b158015614569575f80fd5b505af115801561457b573d5f803e3d5ffd5b50505050505050565b5f6139dd83836149b9565b6001600160a01b0381166145f45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b65565b6007546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3600780546001600160a01b0319166001600160a01b0392909216919091179055565b5f8061465b83856155bb565b9050838110156139dd5760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610b65565b5f8181526001830160205260408120548015614787575f6146cf600183615486565b85549091505f906146e290600190615486565b9050818114614741575f865f018281548110614700576147006152bc565b905f5260205f200154905080875f018481548110614720576147206152bc565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806147525761475261564f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050611394565b5f915050611394565b5092915050565b5f81836147b75760405162461bcd60e51b8152600401610b659190615663565b505f6147c38486615473565b95945050505050565b5f81848411156147ef5760405162461bcd60e51b8152600401610b659190615663565b505f6147c38486615486565b5f61484f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b189092919063ffffffff16565b805190915015613b52578080602001905181019061486d91906154e7565b613b525760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610b65565b6001600160a01b0382165f90815260046020526040902080549082905580821115614925575f6148fc8383613aae565b90506149088482614b26565b8060055f82825461491991906155bb565b90915550613b52915050565b80821015613b52575f6149388284613aae565b90506149448482614b7e565b8060055f8282546149559190615486565b909155505050505050565b6060815f018054806020026020016040519081016040528092919081815260200182805480156149ad57602002820191905f5260205f20905b815481526020019060010190808311614999575b50505050509050919050565b5f8181526001830160205260408120546149fe57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155611394565b505f611394565b801580614a7d5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015614a57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614a7b9190615499565b155b614ae85760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610b65565b6040516001600160a01b038316602482015260448101829052613b5290849063095ea7b360e01b90606401613b1b565b6060612a0484845f85614bb7565b614b5f614b4161137a836001546139ef90919063ffffffff16565b6001600160a01b0384165f9081526002602052604090205490614c8e565b6001600160a01b039092165f9081526002602052604090209190915550565b614b5f614b9961137a836001546139ef90919063ffffffff16565b6001600160a01b0384165f9081526002602052604090205490613baf565b606082471015614c185760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610b65565b5f80866001600160a01b03168587604051614c339190615698565b5f6040518083038185875af1925050503d805f8114614c6d576040519150601f19603f3d011682016040523d82523d5f602084013e614c72565b606091505b5091509150614c8387838387614cc7565b979650505050505050565b5f80614c9a83856156ae565b90505f8312158015614cac5750838113155b80613be157505f83128015613be157508381136139dd575f80fd5b60608315614d355782515f03614d2e576001600160a01b0385163b614d2e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b65565b5081612a04565b612a048383815115614d4a5781518083602001fd5b8060405162461bcd60e51b8152600401610b659190615663565b80356001600160a01b0381168114614399575f80fd5b5f60208284031215614d8a575f80fd5b6139dd82614d64565b5f60208284031215614da3575f80fd5b5035919050565b80151581146127ee575f80fd5b803561439981614daa565b5f60208284031215614dd2575f80fd5b81356139dd81614daa565b602080825282518282018190525f918401906040840190835b81811015614e14578351835260209384019390920191600101614df6565b509095945050505050565b803565ffffffffffff81168114614399575f80fd5b5f8060408385031215614e45575f80fd5b82359150614e5560208401614e1f565b90509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614e9b57614e9b614e5e565b604052919050565b5f67ffffffffffffffff821115614ebc57614ebc614e5e565b5060051b60200190565b5f82601f830112614ed5575f80fd5b8135614ee8614ee382614ea3565b614e72565b8082825260208201915060208360051b860101925085831115614f09575f80fd5b602085015b83811015614f2d57614f1f81614d64565b835260209283019201614f0e565b5095945050505050565b5f805f60608486031215614f49575f80fd5b833567ffffffffffffffff811115614f5f575f80fd5b614f6b86828701614ec6565b935050602084013567ffffffffffffffff811115614f87575f80fd5b8401601f81018613614f97575f80fd5b8035614fa5614ee382614ea3565b8082825260208201915060208360051b850101925088831115614fc6575f80fd5b6020840193505b82841015614ff657833560ff81168114614fe5575f80fd5b825260209384019390910190614fcd565b94506150089250505060408501614db7565b90509250925092565b5f82601f830112615020575f80fd5b813561502e614ee382614ea3565b8082825260208201915060208360051b86010192508583111561504f575f80fd5b602085015b83811015614f2d5761506581614e1f565b835260209283019201615054565b5f805f60608486031215615085575f80fd5b833567ffffffffffffffff81111561509b575f80fd5b6150a786828701614ec6565b935050602084013567ffffffffffffffff8111156150c3575f80fd5b8401601f810186136150d3575f80fd5b80356150e1614ee382614ea3565b8082825260208201915060208360051b850101925088831115615102575f80fd5b6020840193505b828410156151385783356001600160701b0381168114615127575f80fd5b825260209384019390910190615109565b9450505050604084013567ffffffffffffffff811115615156575f80fd5b61516286828701615011565b9150509250925092565b5f610140820190506001600160701b0387511682526001600160701b03602088015116602083015265ffffffffffff604088015116604083015260608701511515606083015260ff608088015116608083015260a087015160a08301526151de60c08301876001600160a01b03169052565b8460e083015283610100830152826101208301529695505050505050565b5f6020828403121561520c575f80fd5b813567ffffffffffffffff811115615222575f80fd5b612a0484828501614ec6565b5f6020828403121561523e575f80fd5b6139dd82614e1f565b5f8060408385031215615258575f80fd5b50508035926020909101359150565b5f8151808452602084019350602083015f5b828110156152a05781516001600160a01b0316865260209586019590910190600101615279565b5093949350505050565b602081525f6139dd6020830184615267565b634e487b7160e01b5f52603260045260245ffd5b828152604060208201525f612a046040830184615267565b5f602082840312156152f8575f80fd5b815167ffffffffffffffff81111561530e575f80fd5b8201601f8101841361531e575f80fd5b805161532c614ee382614ea3565b8082825260208201915060208360051b85010192508683111561534d575f80fd5b6020840193505b8284101561536f578351825260209384019390910190615354565b9695505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b6001600160701b038181168382160290811690818114614790576147906153e5565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160701b038316806154475761544761541b565b806001600160701b0384160491505092915050565b8082028115828204841417611394576113946153e5565b5f826154815761548161541b565b500490565b81810381811115611394576113946153e5565b5f602082840312156154a9575f80fd5b5051919050565b6020808252601a908201527f496e73756666696369656e7420746f6b656e2072657761726473000000000000604082015260600190565b5f602082840312156154f7575f80fd5b81516139dd81614daa565b6001600160701b038281168282160390811115611394576113946153e5565b602080825260169082015275125b9d985b1a59081cdd185ada5b99c81c195c9a5bd960521b604082015260600190565b60208082526029908201527f43616e6e6f74207374616b6520666f7220612073686f7274657220706572696f60408201526864206f662074696d6560b81b606082015260800190565b65ffffffffffff8181168382160290811690818114614790576147906153e5565b80820180821115611394576113946153e5565b6001600160701b038181168382160190811115611394576113946153e5565b8082018281125f83128015821682158216171561560c5761560c6153e5565b505092915050565b85815284602082015260a060408201525f61563260a0830186615267565b6001600160a01b0394909416606083015250608001529392505050565b634e487b7160e01b5f52603160045260245ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f82518060208501845e5f920191825250919050565b8181035f831280158383131683831282161715614790576147906153e556fe1e644784312a20029e0b26f09d7855f9c06c5daf598ae7dc9188a367bc3d5560a264697066735822122030264ee90ed4584ef1762f9d6f29c85230987a19867ecc1caa8ee3ca711cd70b64736f6c634300081a0033
Verified Source Code Full Match
Compiler: v0.8.26+commit.8a97fa7a
EVM: cancun
Optimization: Yes (200 runs)
VoxStaking.sol 1930 lines
//SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
interface IDexRouter {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
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);
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, 'SafeMath: addition overflow');
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, 'SafeMath: subtraction overflow');
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, 'SafeMath: multiplication overflow');
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, 'SafeMath: division by zero');
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, 'SafeMath: modulo by zero');
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x < y ? x : y;
}
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
library SafeMathInt {
int256 private constant MIN_INT256 = int256(1) << 255;
int256 private constant MAX_INT256 = ~(int256(1) << 255);
/**
* @dev Multiplies two int256 variables and fails on overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
int256 c = a * b;
// Detect overflow when multiplying MIN_INT256 with -1
require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
require((b == 0) || (c / b == a));
return c;
}
/**
* @dev Division of two int256 variables and fails on overflow.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
// Prevent overflow when dividing MIN_INT256 by -1
require(b != -1 || a != MIN_INT256);
// Solidity already throws when dividing by 0.
return a / b;
}
/**
* @dev Subtracts two int256 variables and fails on overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a));
return c;
}
/**
* @dev Adds two int256 variables and fails on overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a));
return c;
}
/**
* @dev Converts to absolute value, and fails on overflow.
*/
function abs(int256 a) internal pure returns (int256) {
require(a != MIN_INT256);
return a < 0 ? -a : a;
}
function toUint256Safe(int256 a) internal pure returns (uint256) {
require(a >= 0);
return uint256(a);
}
}
library SafeMathUint {
function toInt256Safe(uint256 a) internal pure returns (int256) {
int256 b = int256(a);
require(b >= 0);
return b;
}
}
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface DividendPayingContractOptionalInterface {
function withdrawableDividendOf(address _owner) external view returns(uint256);
function withdrawnDividendOf(address _owner) external view returns(uint256);
function accumulativeDividendOf(address _owner) external view returns(uint256);
}
interface DividendPayingContractInterface {
function dividendOf(address _owner) external view returns(uint256);
function withdrawDividend() external;
event DividendsDistributed(
address indexed from,
uint256 usdtAmount
);
event DividendWithdrawn(
address indexed to,
uint256 usdtAmount
);
}
contract DividendPayingContract is DividendPayingContractInterface, DividendPayingContractOptionalInterface {
using SafeMath for uint256;
using SafeMathUint for uint256;
using SafeMathInt for int256;
using SafeERC20 for IERC20;
uint256 constant internal magnitude = 2**128;
uint256 internal magnifiedDividendPerShare;
mapping(address => int256) internal magnifiedDividendCorrections;
mapping(address => uint256) internal withdrawnDividends;
mapping (address => uint256) public holderBalance;
uint256 public totalBalance;
IERC20 public immutable USDT;
uint256 public totalDividendsDistributed;
function distributeDividends(uint256 amount) internal {
if(totalBalance > 0 && amount > 0){
magnifiedDividendPerShare = magnifiedDividendPerShare.add(
(amount).mul(magnitude) / totalBalance
);
emit DividendsDistributed(msg.sender, amount);
totalDividendsDistributed = totalDividendsDistributed.add(amount);
}
}
function withdrawDividend() external virtual override {
_withdrawDividendOfUser(payable(msg.sender));
}
function _withdrawDividendOfUser(address payable user) internal returns (uint256) {
uint256 _withdrawableDividend = withdrawableDividendOf(user);
if (_withdrawableDividend > 0) {
withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend);
emit DividendWithdrawn(user, _withdrawableDividend);
USDT.safeTransfer(user, _withdrawableDividend);
return _withdrawableDividend;
}
return 0;
}
function dividendOf(address _owner) external view override returns(uint256) {
return withdrawableDividendOf(_owner);
}
function withdrawableDividendOf(address _owner) public view override returns(uint256) {
return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
}
function withdrawnDividendOf(address _owner) external view override returns(uint256) {
return withdrawnDividends[_owner];
}
function accumulativeDividendOf(address _owner) public view override returns(uint256) {
return magnifiedDividendPerShare.mul(holderBalance[_owner]).toInt256Safe()
.add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude;
}
function _increase(address account, uint256 value) internal {
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
.sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
}
function _reduce(address account, uint256 value) internal {
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
.add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );
}
function _setBalance(address account, uint256 newBalance) internal {
uint256 currentBalance = holderBalance[account];
holderBalance[account] = newBalance;
if(newBalance > currentBalance) {
uint256 increaseAmount = newBalance.sub(currentBalance);
_increase(account, increaseAmount);
totalBalance += increaseAmount;
} else if(newBalance < currentBalance) {
uint256 reduceAmount = currentBalance.sub(newBalance);
_reduce(account, reduceAmount);
totalBalance -= reduceAmount;
}
}
}
contract DividendTracker is DividendPayingContract {
event Claim(address indexed account, uint256 amount, bool indexed automatic);
constructor() {}
function getAccount(address _account)
public view returns (
address account,
uint256 withdrawableDividends,
uint256 totalDividends,
uint256 balance) {
account = _account;
withdrawableDividends = withdrawableDividendOf(account);
totalDividends = accumulativeDividendOf(account);
balance = holderBalance[account];
}
function setBalance(address payable account, uint256 newBalance) internal {
_setBalance(account, newBalance);
processAccount(account, true);
}
function processAccount(address payable account, bool automatic) internal returns (bool) {
uint256 amount = _withdrawDividendOfUser(account);
if(amount > 0) {
emit Claim(account, amount, automatic);
return true;
}
return false;
}
function getTotalDividendsDistributed() external view returns (uint256) {
return totalDividendsDistributed;
}
function dividendTokenBalanceOf(address account) public view returns (uint256) {
return holderBalance[account];
}
function getNumberOfDividends() external view returns(uint256) {
return totalBalance;
}
}
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
contract Context {
constructor() {}
function _msgSender() internal view returns (address payable) {
return payable(msg.sender);
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), 'Ownable: caller is not the owner');
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = 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 onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), 'Ownable: new owner is the zero address');
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* @title VoxStaking
* @notice Unified staking contract for VOX tokens with dual reward system
* @dev Users stake VOX tokens and earn both USDT dividends and additional VOX token rewards
* Features time-locked staking with boost multipliers, emergency withdrawal, and compounding
*/
contract VoxStaking is ReentrancyGuard, DividendTracker, Ownable {
/// @notice The VOX token contract (immutable)
IERC20 public immutable voxToken;
/// @notice The WETH token contract for DEX operations (immutable)
IERC20 public immutable WETH;
/// @notice The DEX router for token swapping during compound operations (immutable)
IDexRouter public immutable dexRouter;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableSet for EnumerableSet.AddressSet;
using SafeERC20 for IERC20;
using SafeMath for uint256;
/// @notice Set of valid staking periods in days
EnumerableSet.UintSet private stakingPeriodsInDays;
/// @notice Mapping of staking period (days) to boost percentage (e.g., 100 = 100% boost = 2x multiplier)
mapping (uint256 => uint256) public stakingPeriodBoost;
/// @notice Default emergency withdrawal penalty percentage (e.g., 50 = 50%)
uint256 public emergencyWithdrawPenalty;
// ═══════════════════════════════════════════════════════════════════════════════
// TOKEN EMISSIONS STAKING VARIABLES
// ═══════════════════════════════════════════════════════════════════════════════
/// @notice VOX tokens distributed per second to all stakers
uint256 public tokenRewardsPerSecond;
/// @notice Last timestamp when token pool rewards were updated
uint256 public tokenLastRewardTimestamp;
/// @notice Accumulated VOX tokens per share, scaled by 1e12 for precision
uint256 public tokenAccTokensPerShare;
/// @notice Total amount of VOX tokens currently staked (raw amount, not boosted)
uint256 public tokenTotalStaked;
/// @notice Whether token emission rewards are currently active
bool public tokenRewardsActive;
// ═══════════════════════════════════════════════════════════════════════════════
// USER DATA STRUCTURE
// ═══════════════════════════════════════════════════════════════════════════════
/**
* @notice User staking information combining both USDT dividend and VOX token reward tracking
* @dev Optimized struct packing to minimize storage costs
*/
struct User {
/// @notice Base amount of VOX tokens staked (before boost multiplier)
uint112 baseTokensStaked;
/// @notice Timestamp when tokens can be withdrawn (unlock time)
uint112 holderUnlockTime;
/// @notice Duration of staking period in days (30, 90, or 180)
uint48 stakingDuration;
/// @notice Whether user has a custom emergency withdrawal penalty
bool hasCustomEmergencyWithdrawPenalty;
/// @notice Custom emergency withdrawal penalty percentage (0-100)
uint8 customEmergencyWithdrawPenalty;
/// @notice Reward debt for VOX token emissions (prevents double-claiming)
uint256 tokenRewardDebt;
}
/// @notice Mapping of user addresses to their staking information
mapping (address => User) public users;
/// @notice Set of all users who have ever staked (for iteration)
EnumerableSet.AddressSet private userList;
/// @notice Last known USDT balance for automatic dividend detection
uint256 private lastKnownUsdtBalance;
// ═══════════════════════════════════════════════════════════════════════════════
// EVENTS
// ═══════════════════════════════════════════════════════════════════════════════
/// @notice Emitted when a user deposits VOX tokens
event Deposit(address indexed user, uint256 amount);
/// @notice Emitted when a user withdraws VOX tokens
event Withdraw(address indexed user, uint256 amount);
/// @notice Emitted when a user performs emergency withdrawal
event EmergencyWithdraw(address indexed user, uint256 amountForUser, uint256 amountForPenalty);
/// @notice Emitted when VOX token rewards are paid to a user
event TokenRewardsPaid(address indexed user, uint256 amount);
/// @notice Emitted when VOX token rewards are paid to a user
event Claim(address indexed user, uint256 amount);
/**
* @notice Initializes the VoxStaking contract
* @dev Sets up staking periods, boost multipliers, and chain-specific token addresses
* @param _voxToken Address of the VOX token contract
*/
constructor(address _voxToken) {
require(_voxToken != address(0), "cannot be 0 address");
voxToken = IERC20(_voxToken);
// Initialize staking periods and their corresponding boost multipliers
// 30 days = 0% boost (1x multiplier)
// 90 days = 100% boost (2x multiplier)
// 180 days = 200% boost (3x multiplier)
stakingPeriodsInDays.add(30);
stakingPeriodsInDays.add(90);
stakingPeriodsInDays.add(180);
stakingPeriodBoost[30] = 0;
stakingPeriodBoost[90] = 100;
stakingPeriodBoost[180] = 200;
// Initialize token emissions staking with disabled state
tokenRewardsPerSecond = 0;
tokenLastRewardTimestamp = 99999999999; // Far future timestamp
tokenAccTokensPerShare = 0;
tokenTotalStaked = 0;
tokenRewardsActive = false;
// Set up chain-specific contract addresses for DEX operations
address _v2Router;
address _USDT;
address _WETH;
// Configure addresses based on the deployed chain
if(block.chainid == 1){ // Ethereum Mainnet
_v2Router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; // Uniswap V2 Router
_USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7; // USDT
_WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // WETH
} else if(block.chainid == 8453){ // Base Mainnet
_v2Router = 0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24; // Base DEX Router
_USDT = 0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2; // USDT on Base
_WETH = 0x4200000000000000000000000000000000000006; // WETH on Base
} else {
revert("Chain not configured");
}
dexRouter = IDexRouter(_v2Router);
USDT = IERC20(_USDT);
WETH = IERC20(_WETH);
// Set default emergency withdrawal penalty to 50%
emergencyWithdrawPenalty = 50;
}
// ═══════════════════════════════════════════════════════════════════════════════
// TOKEN EMISSIONS STAKING FUNCTIONS
// ═══════════════════════════════════════════════════════════════════════════════
/**
* @notice Starts the token rewards distribution system
* @dev Can only be called by the contract owner. Requires rewards per second to be set first.
*/
function startTokenRewards() external onlyOwner {
require(!tokenRewardsActive, "Rewards already active");
require(tokenRewardsPerSecond > 0, "Rewards per second must be set");
tokenLastRewardTimestamp = block.timestamp;
tokenRewardsActive = true;
}
/**
* @notice Stops the token rewards distribution system
* @dev Can only be called by the contract owner. Updates pool before stopping.
*/
function stopTokenRewards() external onlyOwner {
updateTokenPool();
tokenRewardsPerSecond = 0;
tokenRewardsActive = false;
}
/**
* @notice Sets the rate of VOX token rewards distributed per second
* @dev Can only be called by the contract owner. Updates pool before changing rate.
* @param newRewardsPerSecond New reward rate in VOX tokens per second (in wei)
*/
function setTokenRewardsPerSecond(uint256 newRewardsPerSecond) external onlyOwner {
updateTokenPool();
tokenRewardsPerSecond = newRewardsPerSecond;
}
/**
* @notice Updates the token reward pool with new accumulated rewards
* @dev Internal function called before any staking state changes to ensure accurate reward calculations
*/
function updateTokenPool() internal {
if (block.timestamp <= tokenLastRewardTimestamp) {
return;
}
uint256 lpSupply = totalBalance;
if (lpSupply == 0) {
tokenLastRewardTimestamp = block.timestamp;
return;
}
uint256 tokenReward = calculateTokenNewRewards();
if (tokenReward == 0) {
tokenLastRewardTimestamp = block.timestamp;
return;
}
tokenAccTokensPerShare = tokenAccTokensPerShare.add(
tokenReward.mul(1e12).div(lpSupply)
);
tokenLastRewardTimestamp = block.timestamp;
}
/**
* @notice Calculates the amount of new VOX token rewards since last update
* @dev Public view function that can be used to preview pending rewards
* @return Amount of new VOX token rewards in wei
*/
function calculateTokenNewRewards() public view returns (uint256) {
if (tokenLastRewardTimestamp > block.timestamp || !tokenRewardsActive) {
return 0;
}
return ((block.timestamp - tokenLastRewardTimestamp) * tokenRewardsPerSecond);
}
/**
* @notice Calculates pending VOX token rewards for a specific user
* @dev Uses the user's boosted balance for reward calculations
* @param _user Address of the user to check pending rewards for
* @return Amount of pending VOX token rewards in wei
*/
function pendingTokenReward(address _user) external view returns (uint256) {
User storage user = users[_user];
if (user.baseTokensStaked == 0) {
return 0;
}
uint256 accTokensPerShare = tokenAccTokensPerShare;
if (block.timestamp > tokenLastRewardTimestamp && totalBalance != 0) {
uint256 multiplier = block.timestamp - tokenLastRewardTimestamp;
uint256 rewards = multiplier * tokenRewardsPerSecond;
accTokensPerShare = accTokensPerShare + (rewards * 1e12 / totalBalance);
}
return holderBalance[_user].mul(accTokensPerShare).div(1e12).sub(user.tokenRewardDebt);
}
/**
* @notice Gets comprehensive token staking information for a specific user
* @dev Returns all relevant data for token reward tracking
* @param _user Address of the user to query
* @return amount Base amount of VOX tokens staked (before boost)
* @return rewardDebt Current reward debt for preventing double-claiming
* @return unlockTime Timestamp when tokens can be withdrawn
* @return pendingReward Current pending VOX token rewards
*/
function getTokenUserInfo(address _user) external view returns (
uint256 amount,
uint256 rewardDebt,
uint256 unlockTime,
uint256 pendingReward
) {
User storage user = users[_user];
amount = user.baseTokensStaked;
rewardDebt = user.tokenRewardDebt;
unlockTime = user.holderUnlockTime;
pendingReward = this.pendingTokenReward(_user);
}
/**
* @notice Gets comprehensive information about the token staking pool
* @dev Returns all relevant pool statistics and parameters
* @return totalStaked Total amount of VOX tokens currently staked
* @return rewardsPerSecond Current reward distribution rate
* @return lastRewardTimestamp Last time rewards were calculated
* @return accTokensPerShare Accumulated tokens per share (scaled by 1e12)
* @return rewardsActive Whether token rewards are currently active
*/
function getTokenPoolInfo() external view returns (
uint256 totalStaked,
uint256 rewardsPerSecond,
uint256 lastRewardTimestamp,
uint256 accTokensPerShare,
bool rewardsActive
) {
totalStaked = tokenTotalStaked;
rewardsPerSecond = tokenRewardsPerSecond;
lastRewardTimestamp = tokenLastRewardTimestamp;
accTokensPerShare = tokenAccTokensPerShare;
rewardsActive = tokenRewardsActive;
}
// Owner functions
// @dev Sets custom emergency withdraw penalties by wallet
function setCustomEmergencyWithdrawPenalty(address[] memory _addresses, uint8[] memory _customEmergencyWithdrawPenalty, bool _hasCustomEmergencyWithdrawPenalty) external onlyOwner {
for(uint256 i = 0; i < _addresses.length; i++){
address addy = _addresses[i];
User memory user = users[addy];
if(_hasCustomEmergencyWithdrawPenalty){
uint8 customEmergencyWithdrawPenalty = _customEmergencyWithdrawPenalty[i];
require(customEmergencyWithdrawPenalty <= 100, "Cannot set emergency penalty over 100%");
user.hasCustomEmergencyWithdrawPenalty = true;
us...
// [truncated — 77111 bytes total]
Read Contract
USDT 0xc54e44eb → address
WETH 0xad5c4648 → address
accumulativeDividendOf 0x27ce0147 → uint256
balanceOf 0x70a08231 → uint256
calculateTokenNewRewards 0x2d141467 → uint256
dexRouter 0x0758d924 → address
dividendOf 0x91b89fba → uint256
dividendTokenBalanceOf 0x6843cd84 → uint256
emergencyWithdrawPenalty 0x583a6c34 → uint256
getAccount 0xfbcbc0f1 → address, uint256, uint256, uint256
getExpectedCompoundOutputByUsdtAmount 0x3865d2b5 → uint256
getExpectedCompoundOutputByWallet 0x08f2f233 → uint256
getLockPeriodEnd 0xd5cb06c4 → uint256
getNumberOfDividends 0x71778e7d → uint256
getTokenPoolInfo 0xd7b6453f → uint256, uint256, uint256, uint256, bool
getTokenUserInfo 0xd664c0c8 → uint256, uint256, uint256, uint256
getTotalDividendsDistributed 0x30bb4cff → uint256
getUser 0x6f77926b → tuple, address, uint256, uint256, uint256
getUserList 0xb8522043 → address[]
getValidStakingDurations 0x2e29490d → uint256[]
holderBalance 0xab6ddfa8 → uint256
owner 0x8da5cb5b → address
pendingTokenReward 0x71a0f50e → uint256
stakingPeriodBoost 0xfa50c7d0 → uint256
tokenAccTokensPerShare 0x7be1ee97 → uint256
tokenLastRewardTimestamp 0xca5b7465 → uint256
tokenRewardsActive 0x2b2e0d5d → bool
tokenRewardsPerSecond 0x45d05c42 → uint256
tokenTotalStaked 0x872b26da → uint256
totalBalance 0xad7a672f → uint256
totalDividendsDistributed 0x85a6b3ae → uint256
users 0xa87430ba → uint112, uint112, uint48, bool, uint8, uint256
voxToken 0x514d8a17 → address
withdrawableDividendOf 0xa8b9d240 → uint256
withdrawnDividendOf 0xaafd847a → uint256
Write Contract 25 functions
These functions modify contract state and require a wallet transaction to execute.
addStakingPeriod 0xd9b26a69
uint256 _newStakingPeriod
uint256 _newStakingBoost
allocateStake 0x5ad31e99
address[] _addresses
uint112[] _amounts
uint48[] _durations
autoDistributeUsdtDividends 0xd5eb9113
No parameters
checkAndDistributeUsdt 0xf0739147
No parameters
claim 0x4e71d92d
No parameters
claimTokens 0x48c54b9d
No parameters
compound 0xaa5f7e26
uint256 minOutput
deposit 0x37b90a4f
uint256 _amount
uint48 _stakingDurationInDays
emergencyWithdrawTokens 0x1d5d7cc9
bool ignoreRewards
extendLock 0x814eaeea
uint48 _stakingDurationInDays
forceUpdate 0x7231c394
address[] _addresses
forceUpdateAll 0xa9c66b14
No parameters
receiveUsdtAndDistribute 0x7882bd33
uint256 amount
removeStakingPeriod 0x1b90e0e8
uint256 _newStakingPeriod
renounceOwnership 0x715018a6
No parameters
setCustomEmergencyWithdrawPenalty 0x51a8ea63
address[] _addresses
uint8[] _customEmergencyWithdrawPenalty
bool _hasCustomEmergencyWithdrawPenalty
setTokenRewardsPerSecond 0x1a2c2e86
uint256 newRewardsPerSecond
startTokenRewards 0x0fc924e3
No parameters
stopTokenRewards 0x17460b1b
No parameters
transferOwnership 0xf2fde38b
address newOwner
updateEmergencyWithdrawPenalty 0xdae97c1b
uint256 _newPerc
updateStakingBoost 0x94463e98
uint256 _stakingPeriod
uint256 _newStakingBoost
withdrawDividend 0x6a474002
No parameters
withdrawRewardTokens 0xcb43b2dd
uint256 _amount
withdrawTokens 0x315a095d
uint256 _amount
Recent Transactions
No transactions found for this address