Address Contract Verified
Address
0xbDeEcD45c5CD469A3e23dB73D7364d40Ac3376D1
Balance
0 ETH
Nonce
4
Code Size
11363 bytes
Creator
0x222d81F2...ebB5 at tx 0xfddfde6e...b7c2ce
Indexed Transactions
0
Contract Bytecode
11363 bytes
0x6080604052600436106200011f5760003560e01c806374a110c211620000a1578063ac4afa38116200006c578063ac4afa3814620002e7578063c81bf2b1146200032c578063c88f8f5b1462000359578063d88ff1f41462000371578063f2fde38b146200039857600080fd5b806374a110c214620002585780638c5114aa146200027d5780638da5cb5b14620002a2578063a38dcbd014620002c257600080fd5b806347c3194511620000ee57806347c31945146200019f5780636247d04914620001b7578063676346ad14620001dc578063715018a6146200020157806372f702f3146200021957600080fd5b80631324968d1462000124578063152111f7146200014b5780631d8092f314620001555780633c9fc7cb146200017a575b600080fd5b3480156200013157600080fd5b506200014962000143366004620011a4565b620003bd565b005b62000149620004b5565b3480156200016257600080fd5b506200014962000174366004620011fb565b620006a5565b3480156200018757600080fd5b506200014962000199366004620012a0565b6200078a565b348015620001ac57600080fd5b50620001496200082f565b348015620001c457600080fd5b5062000149620001d6366004620012ba565b6200088c565b348015620001e957600080fd5b5062000149620001fb366004620011a4565b620009b8565b3480156200020e57600080fd5b506200014962000a90565b3480156200022657600080fd5b506001546200023b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156200026557600080fd5b50620001496200027736600462001310565b62000aa8565b3480156200028a57600080fd5b50620001496200029c366004620012ba565b62000bc7565b348015620002af57600080fd5b506000546001600160a01b03166200023b565b348015620002cf57600080fd5b5062000149620002e1366004620012a0565b62000cf3565b348015620002f457600080fd5b506200030c62000306366004620012a0565b62000e24565b604080516001600160a01b0390931683526020830191909152016200024f565b3480156200033957600080fd5b50600354620003489060ff1681565b60405190151581526020016200024f565b3480156200036657600080fd5b506200014962000e5d565b3480156200037e57600080fd5b506200038962000f13565b6040516200024f919062001333565b348015620003a557600080fd5b5062000149620003b73660046200138d565b62000f8a565b620003c762001006565b600060028190555b81518110156200046c57818181518110620003ee57620003ee620013b4565b602002602001015160026000828254620004099190620013e0565b92505081905550818181518110620004255762000425620013b4565b602002602001015160048281548110620004435762000443620013b4565b6000918252602090912060016002909202010155806200046381620013fb565b915050620003cf565b506127106002541115620004b25760405162461bcd60e51b81526020600482015260086024820152676c7465203130302560c01b60448201526064015b60405180910390fd5b50565b60003411620004f45760405162461bcd60e51b815260206004820152600a6024820152696e6f207265776172647360b01b6044820152606401620004a9565b6000805b600454811015620005f857600082905061271060048381548110620005215762000521620013b4565b9060005260206000209060020201600101543462000540919062001419565b6200054c91906200143b565b620005589084620013e0565b925060048281548110620005705762000570620013b4565b60009182526020909120600290910201546001600160a01b031663152111f76200059b83866200145e565b6040518263ffffffff1660e01b81526004016000604051808303818588803b158015620005c757600080fd5b505af1158015620005dc573d6000803e3d6000fd5b5050505050508080620005ef90620013fb565b915050620004f8565b5060006200060782346200145e565b90508015620006a157604051600090339083908381818185875af1925050503d806000811462000654576040519150601f19603f3d011682016040523d82523d6000602084013e62000659565b606091505b50509050806200069f5760405162461bcd60e51b815260206004820152601060248201526f18dbdd5b19081b9bdd081c99599d5b9960821b6044820152606401620004a9565b505b5050565b620006af62001006565b60005b8151811015620006a15760048181548110620006d257620006d2620013b4565b600091825260209091206002909102015482516001600160a01b039091169063b2a7e224908490849081106200070c576200070c620013b4565b60200260200101516040518263ffffffff1660e01b81526004016200074091906001600160a01b0391909116815260200190565b600060405180830381600087803b1580156200075b57600080fd5b505af115801562000770573d6000803e3d6000fd5b5050505080806200078190620013fb565b915050620006b2565b60005b81811015620006a15760048181548110620007ac57620007ac620013b4565b600091825260208220600290910201546040805163ef8c094f60e01b815233600482015290516001600160a01b039092169263ef8c094f9260248084019382900301818387803b1580156200080057600080fd5b505af115801562000815573d6000803e3d6000fd5b5050505080806200082690620013fb565b9150506200078d565b6200083962001006565b60035460ff16620008805760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e48191a5cd8589b195960821b6044820152606401620004a9565b6003805460ff19169055565b6200089662001006565b60035460ff16620008d55760405162461bcd60e51b8152602060048201526008602482015267191a5cd8589b195960c21b6044820152606401620004a9565b60005b81518110156200069f5760048181548110620008f857620008f8620013b4565b600091825260209091206002909102015482516001600160a01b0390911690634782f779908590859085908110620009345762000934620013b4565b60200260200101516040518363ffffffff1660e01b81526004016200096e9291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b1580156200098957600080fd5b505af11580156200099e573d6000803e3d6000fd5b505050508080620009af90620013fb565b915050620008d8565b620009c262001006565b60005b8151811015620006a15760048181548110620009e557620009e5620013b4565b600091825260209091206002909102015482516001600160a01b039091169063c771c3909084908490811062000a1f5762000a1f620013b4565b60200260200101516040518263ffffffff1660e01b815260040162000a4691815260200190565b600060405180830381600087803b15801562000a6157600080fd5b505af115801562000a76573d6000803e3d6000fd5b50505050808062000a8790620013fb565b915050620009c5565b62000a9a62001006565b62000aa6600062001062565b565b62000ab262001006565b6127108160025462000ac59190620013e0565b111562000b065760405162461bcd60e51b815260206004820152600e60248201526d6d61782070657263656e7461676560901b6044820152606401620004a9565b806002600082825462000b1a9190620013e0565b9091555050604080518082019182905260015460049282916001600160a01b031690869062000b4990620010b2565b6001600160a01b0390921682526020820152604001604051809103906000f08015801562000b7b573d6000803e3d6000fd5b506001600160a01b039081168252602091820194909452825460018082018555600094855293829020835160029092020180546001600160a01b03191691909516178455015191015550565b62000bd162001006565b60035460ff1662000c105760405162461bcd60e51b8152602060048201526008602482015267191a5cd8589b195960c21b6044820152606401620004a9565b60005b81518110156200069f576004818154811062000c335762000c33620013b4565b600091825260209091206002909102015482516001600160a01b03909116906306b091f990859085908590811062000c6f5762000c6f620013b4565b60200260200101516040518363ffffffff1660e01b815260040162000ca99291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b15801562000cc457600080fd5b505af115801562000cd9573d6000803e3d6000fd5b50505050808062000cea90620013fb565b91505062000c13565b62000cfd62001006565b60006004828154811062000d155762000d15620013b4565b6000918252602080832060408051808201909152600293840290910180546001600160a01b0316825260010154918101829052825490945090929062000d5d9084906200145e565b90915550506004805462000d74906001906200145e565b8154811062000d875762000d87620013b4565b90600052602060002090600202016004838154811062000dab5762000dab620013b4565b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b03909216919091178155600191820154910155600480548062000df75762000df762001478565b60008281526020812060026000199093019283020180546001600160a01b03191681556001015590555050565b6004818154811062000e3557600080fd5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b62000e6762001006565b60005b60045481101562000f08576004818154811062000e8b5762000e8b620013b4565b60009182526020822060029091020154604080516338a80c5360e11b815290516001600160a01b039092169263715018a69260048084019382900301818387803b15801562000ed957600080fd5b505af115801562000eee573d6000803e3d6000fd5b50505050808062000eff90620013fb565b91505062000e6a565b5062000aa662000a90565b60606004805480602002602001604051908101604052809291908181526020016000905b8282101562000f81576000848152602090819020604080518082019091526002850290910180546001600160a01b0316825260019081015482840152908352909201910162000f37565b50505050905090565b62000f9462001006565b6001600160a01b03811662000ffb5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620004a9565b620004b28162001062565b6000546001600160a01b0316331462000aa65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620004a9565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61179f806200148f83390190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715620011025762001102620010c0565b604052919050565b600067ffffffffffffffff821115620011275762001127620010c0565b5060051b60200190565b600082601f8301126200114357600080fd5b813560206200115c62001156836200110a565b620010d6565b82815260059290921b840181019181810190868411156200117c57600080fd5b8286015b8481101562001199578035835291830191830162001180565b509695505050505050565b600060208284031215620011b757600080fd5b813567ffffffffffffffff811115620011cf57600080fd5b620011dd8482850162001131565b949350505050565b6001600160a01b0381168114620004b257600080fd5b600060208083850312156200120f57600080fd5b823567ffffffffffffffff8111156200122757600080fd5b8301601f810185136200123957600080fd5b80356200124a62001156826200110a565b81815260059190911b820183019083810190878311156200126a57600080fd5b928401925b82841015620012955783356200128581620011e5565b825292840192908401906200126f565b979650505050505050565b600060208284031215620012b357600080fd5b5035919050565b60008060408385031215620012ce57600080fd5b8235620012db81620011e5565b9150602083013567ffffffffffffffff811115620012f857600080fd5b620013068582860162001131565b9150509250929050565b600080604083850312156200132457600080fd5b50508035926020909101359150565b602080825282518282018190526000919060409081850190868401855b828110156200138057815180516001600160a01b0316855286015186850152928401929085019060010162001350565b5091979650505050505050565b600060208284031215620013a057600080fd5b8135620013ad81620011e5565b9392505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115620013f657620013f6620013ca565b500190565b6000600019821415620014125762001412620013ca565b5060010190565b6000816000190483118215151615620014365762001436620013ca565b500290565b6000826200145957634e487b7160e01b600052601260045260246000fd5b500490565b600082821015620014735762001473620013ca565b500390565b634e487b7160e01b600052603160045260246000fdfe608060405234801561001057600080fd5b5060405161179f38038061179f83398101604081905261002f916100b5565b61003833610065565b60018055600580546001600160a01b0319166001600160a01b0393909316929092179091556002556100ef565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080604083850312156100c857600080fd5b82516001600160a01b03811681146100df57600080fd5b6020939093015192949293505050565b6116a1806100fe6000396000f3fe6080604052600436106101405760003560e01c80638da5cb5b116100b6578063ce7c2ac21161006f578063ce7c2ac21461036e578063ee947a7c146103a2578063ef8c094f146103b8578063efca2eed146103d8578063f2fde38b146103ee578063fc0c546a1461040e57600080fd5b80638da5cb5b146102ba57806395319435146102d8578063a694fc3a146102f8578063b2a7e22414610318578063c771c39014610338578063c7e1d0b11461035857600080fd5b80632e17de78116101085780632e17de78146102195780633c6e6789146102395780634782f7791461024f578063715018a61461026f57806380bb40551461028457806389d969171461029a57600080fd5b806306b091f9146101455780630700037d146101675780630e15561a146101b5578063152111f7146101d95780632d5537b0146101e1575b600080fd5b34801561015157600080fd5b506101656101603660046112e6565b61042e565b005b34801561017357600080fd5b5061019b610182366004611312565b6008602052600090815260409020805460019091015482565b604080519283526020830191909152015b60405180910390f35b3480156101c157600080fd5b506101cb600b5481565b6040519081526020016101ac565b6101656104d0565b3480156101ed57600080fd5b50600654610201906001600160a01b031681565b6040516001600160a01b0390911681526020016101ac565b34801561022557600080fd5b50610165610234366004611336565b6104dc565b34801561024557600080fd5b506101cb60045481565b34801561025b57600080fd5b5061016561026a3660046112e6565b610513565b34801561027b57600080fd5b50610165610642565b34801561029057600080fd5b506101cb60035481565b3480156102a657600080fd5b506101cb6102b5366004611312565b610654565b3480156102c657600080fd5b506000546001600160a01b0316610201565b3480156102e457600080fd5b506101656102f3366004611425565b6106da565b34801561030457600080fd5b50610165610313366004611336565b6107c4565b34801561032457600080fd5b50610165610333366004611312565b6107e1565b34801561034457600080fd5b50610165610353366004611336565b61080b565b34801561036457600080fd5b506101cb60095481565b34801561037a57600080fd5b5061019b610389366004611312565b6007602052600090815260409020805460019091015482565b3480156103ae57600080fd5b506101cb60025481565b3480156103c457600080fd5b506101656103d3366004611312565b610858565b3480156103e457600080fd5b506101cb600a5481565b3480156103fa57600080fd5b50610165610409366004611312565b6108b6565b34801561041a57600080fd5b50600554610201906001600160a01b031681565b61043661092c565b6005546001600160a01b03166104cb83831561045257836104ba565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015610496573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ba91906114e7565b6001600160a01b0384169190610986565b505050565b6104da33346109e9565b565b6104e4610aef565b6104fb336005546001600160a01b03169083610986565b61050733826001610b49565b61051060018055565b50565b61051b61092c565b801561063e5760004790506000836001600160a01b0316836040515b60006040518083038185875af1925050503d8060008114610574576040519150601f19603f3d011682016040523d82523d6000602084013e610579565b606091505b50509050806105b75760405162461bcd60e51b8152602060048201526005602482015264044495354360dc1b60448201526064015b60405180910390fd5b6105c18383611516565b4710156105f85760405162461bcd60e51b8152602060048201526005602482015264444953543160d81b60448201526064016105ae565b836001600160a01b03167fe8b160e373db99a103e0a2abfa029b9c3fc8b328984a1ead8a65ae68ae646db78460405161063391815260200190565b60405180910390a250505b5050565b61064a61092c565b6104da6000610c60565b6001600160a01b03811660009081526007602052604081205461067957506000919050565b6001600160a01b03821660009081526007602052604081205461069b90610cb0565b6001600160a01b0384166000908152600860205260409020549091508082116106c8575060009392505050565b6106d28183611516565b949350505050565b6106e2610aef565b805182511461071c5760405162461bcd60e51b8152602060048201526006602482015265494e53594e4360d01b60448201526064016105ae565b6000805b83518110156107a05782818151811061073b5761073b61152d565b60200260200101518261074e9190611543565b915061078e8482815181106107655761076561152d565b602002602001015184838151811061077f5761077f61152d565b60200260200101516000610b49565b806107988161155b565b915050610720565b506107ba335b6005546001600160a01b0316903084610ce0565b5061063e60018055565b6107cc610aef565b6107d5336107a6565b61050733826000610b49565b6107e961092c565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b61081361092c565b6301e1338081106108535760405162461bcd60e51b815260206004820152600a602482015269363a329018903cb2b0b960b11b60448201526064016105ae565b600255565b610860610aef565b61086861092c565b61087181610d1e565b6040516001600160a01b03821681527f63e32091e4445d16e29c33a6b264577c2d86694021aa4e6f4dd590048f5792e89060200160405180910390a161051060018055565b6108be61092c565b6001600160a01b0381166109235760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105ae565b61051081610c60565b6000546001600160a01b031633146104da5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ae565b6040516001600160a01b0383166024820152604481018290526104cb90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610e0d565b60008111610a1f5760405162461bcd60e51b815260206004820152600360248201526208aa8960eb1b60448201526064016105ae565b600060045411610a5a5760405162461bcd60e51b815260206004820152600660248201526553484152455360d01b60448201526064016105ae565b80600b6000828254610a6c9190611543565b9091555050600454610a8d826ec097ce7bc90715b34b9f1000000000611576565b610a979190611595565b60096000828254610aa89190611543565b90915550506040518181526001600160a01b038316907fb9ad861b752f80117b35bea6dec99933d8a5ae360f2839ee8784b750d56134099060200160405180910390a25050565b60026001541415610b425760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105ae565b6002600155565b6006546001600160a01b031615610bc3576006546040516329cc05cf60e01b81526001600160a01b038581166004830152602482018590528315156044830152909116906329cc05cf90606401600060405180830381600087803b158015610bb057600080fd5b505af1925050508015610bc1575060015b505b8015610c1b57610bd38383610ee2565b826001600160a01b03167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd83604051610c0e91815260200190565b60405180910390a2505050565b610c25838361108a565b826001600160a01b03167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a83604051610c0e91815260200190565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006ec097ce7bc90715b34b9f100000000060095483610cd09190611576565b610cda9190611595565b92915050565b6040516001600160a01b0380851660248301528316604482015260648101829052610d189085906323b872dd60e01b906084016109b2565b50505050565b6001600160a01b038116600090815260076020526040902054610d3e5750565b6001600160a01b038116600090815260076020526040812042600190910155610d6682610654565b6001600160a01b038316600090815260086020526040812060010180549293508392909190610d96908490611543565b90915550506001600160a01b038216600090815260076020526040902054610dbd90610cb0565b6001600160a01b038316600090815260086020526040902055801561063e5780600a6000828254610dee9190611543565b909155505060405147906000906001600160a01b038516908490610537565b6000610e62826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166111b19092919063ffffffff16565b9050805160001480610e83575080806020019051810190610e8391906115b7565b6104cb5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016105ae565b6001600160a01b03821660009081526007602052604090205415801590610f2157506001600160a01b0382166000908152600760205260409020548111155b610f5b5760405162461bcd60e51b815260206004820152600b60248201526a1491534e88185b5bdd5b9d60aa1b60448201526064016105ae565b6002546001600160a01b038316600090815260076020526040902060010154610f849190611543565b4211610fc25760405162461bcd60e51b815260206004820152600d60248201526c52454d3a2074696d656c6f636b60981b60448201526064016105ae565b610fcb82610d1e565b8060046000828254610fdd9190611516565b90915550506001600160a01b0382166000908152600760205260408120805483929061100a908490611516565b90915550506001600160a01b0382166000908152600760205260409020426001820155546110485760038054906000611042836115d9565b91905055505b6001600160a01b03821660009081526007602052604090205461106a90610cb0565b6001600160a01b0390921660009081526008602052604090209190915550565b6001600160a01b038216600090815260076020526040902054156110b1576110b182610d1e565b6001600160a01b03821660009081526007602052604081205460048054919284926110dd908490611543565b90915550506001600160a01b0383166000908152600760205260408120805484929061110a908490611543565b90915550506001600160a01b0383166000908152600760205260409020426001909101558015801561115357506001600160a01b03831660009081526007602052604090205415155b1561116e57600380549060006111688361155b565b91905055505b6001600160a01b03831660009081526007602052604090205461119090610cb0565b6001600160a01b039093166000908152600860205260409020929092555050565b60606106d2848460008585600080866001600160a01b031685876040516111d8919061161c565b60006040518083038185875af1925050503d8060008114611215576040519150601f19603f3d011682016040523d82523d6000602084013e61121a565b606091505b509150915061122b87838387611236565b979650505050505050565b606083156112a257825161129b576001600160a01b0385163b61129b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105ae565b50816106d2565b6106d283838151156112b75781518083602001fd5b8060405162461bcd60e51b81526004016105ae9190611638565b6001600160a01b038116811461051057600080fd5b600080604083850312156112f957600080fd5b8235611304816112d1565b946020939093013593505050565b60006020828403121561132457600080fd5b813561132f816112d1565b9392505050565b60006020828403121561134857600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561138e5761138e61134f565b604052919050565b600067ffffffffffffffff8211156113b0576113b061134f565b5060051b60200190565b600082601f8301126113cb57600080fd5b813560206113e06113db83611396565b611365565b82815260059290921b840181019181810190868411156113ff57600080fd5b8286015b8481101561141a5780358352918301918301611403565b509695505050505050565b6000806040838503121561143857600080fd5b823567ffffffffffffffff8082111561145057600080fd5b818501915085601f83011261146457600080fd5b813560206114746113db83611396565b82815260059290921b8401810191818101908984111561149357600080fd5b948201945b838610156114ba5785356114ab816112d1565b82529482019490820190611498565b965050860135925050808211156114d057600080fd5b506114dd858286016113ba565b9150509250929050565b6000602082840312156114f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561152857611528611500565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111561155657611556611500565b500190565b600060001982141561156f5761156f611500565b5060010190565b600081600019048311821515161561159057611590611500565b500290565b6000826115b257634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156115c957600080fd5b8151801515811461132f57600080fd5b6000816115e8576115e8611500565b506000190190565b60005b8381101561160b5781810151838201526020016115f3565b83811115610d185750506000910152565b6000825161162e8184602087016115f0565b9190910192915050565b60208152600082518060208401526116578160408501602087016115f0565b601f01601f1916919091016040019291505056fea264697066735822122025c87d04a75afa5396c77024114f5a6bdde3c147ab8f4fae180dd0243643653864736f6c634300080c0033a26469706673582212205d80dcc7dabbb3ddc0640200365d740bc573e4e4ce5758949926f6784145ef7164736f6c634300080c0033
Verified Source Code Full Match
Compiler: v0.8.12+commit.f00d7308
EVM: london
Optimization: Yes (200 runs)
PoolManager.sol 146 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '@openzeppelin/contracts/access/Ownable.sol';
import './interfaces/IPoolExtension.sol';
import './StakingPool.sol';
contract PoolManager is Ownable {
uint256 constant FACTOR = 10000;
address public stakingToken;
uint256 _totalPercentages;
bool public adminCanWithdraw = true;
struct PoolInfo {
address pool;
uint256 percentage;
}
PoolInfo[] public pools;
constructor(address _stakingToken) {
stakingToken = _stakingToken;
_totalPercentages = FACTOR;
pools.push(
PoolInfo({
pool: address(new StakingPool(_stakingToken, 300)),
percentage: (FACTOR * 3) / 100 // 3%
})
);
pools.push(
PoolInfo({
pool: address(new StakingPool(_stakingToken, 600)),
percentage: (FACTOR * 7) / 100 // 7%
})
);
pools.push(
PoolInfo({
pool: address(new StakingPool(_stakingToken, 900)),
percentage: (FACTOR * 90) / 100 // 90%
})
);
}
function getAllPools() external view returns (PoolInfo[] memory) {
return pools;
}
function depositRewards() external payable {
require(msg.value > 0, 'no rewards');
uint256 _totalETH;
for (uint256 _i; _i < pools.length; _i++) {
uint256 _totalBefore = _totalETH;
_totalETH += (msg.value * pools[_i].percentage) / FACTOR;
StakingPool(pools[_i].pool).depositRewards{
value: _totalETH - _totalBefore
}();
}
uint256 _refund = msg.value - _totalETH;
if (_refund > 0) {
(bool _refunded, ) = payable(_msgSender()).call{ value: _refund }('');
require(_refunded, 'could not refund');
}
}
function claimRewardsBulk(
uint256 lengthPool
) external {
for (uint256 _i; _i < lengthPool; _i++) {
StakingPool(pools[_i].pool).claimRewardAdmin(
_msgSender()
);
}
}
function setLockupPeriods(uint256[] memory _seconds) external onlyOwner {
for (uint256 _i; _i < _seconds.length; _i++) {
StakingPool(pools[_i].pool).setLockupPeriod(_seconds[_i]);
}
}
function setPercentages(uint256[] memory _percentages) external onlyOwner {
_totalPercentages = 0;
for (uint256 _i; _i < _percentages.length; _i++) {
_totalPercentages += _percentages[_i];
pools[_i].percentage = _percentages[_i];
}
require(_totalPercentages <= FACTOR, 'lte 100%');
}
function setExtension(IPoolExtension[] memory _ext) external onlyOwner {
for (uint256 _i; _i < _ext.length; _i++) {
StakingPool(pools[_i].pool).setPoolExtension(_ext[_i]);
}
}
function removeWithdrawAbility() external onlyOwner {
require(adminCanWithdraw, 'already disabled');
adminCanWithdraw = false;
}
function withdrawFromPools(address to, uint256[] memory _amounts) external onlyOwner {
require(adminCanWithdraw, 'disabled');
for (uint256 _i; _i < _amounts.length; _i++) {
StakingPool(pools[_i].pool).withdrawTokens(to, _amounts[_i]);
}
}
function withdrawETHFromPools(address to, uint256[] memory _amounts) external onlyOwner {
require(adminCanWithdraw, 'disabled');
for (uint256 _i; _i < _amounts.length; _i++) {
StakingPool(pools[_i].pool).withdrawETH(to, _amounts[_i]);
}
}
function createPool(
uint256 _lockupSeconds,
uint256 _percentage
) external onlyOwner {
require(_totalPercentages + _percentage <= FACTOR, 'max percentage');
_totalPercentages += _percentage;
pools.push(
PoolInfo({
pool: address(new StakingPool(stakingToken, _lockupSeconds)),
percentage: _percentage
})
);
}
function removePool(uint256 _idx) external onlyOwner {
PoolInfo memory _pool = pools[_idx];
_totalPercentages -= _pool.percentage;
pools[_idx] = pools[pools.length - 1];
pools.pop();
}
function renounceAllOwnership() external onlyOwner {
for (uint256 _i; _i < pools.length; _i++) {
StakingPool(pools[_i].pool).renounceOwnership();
}
renounceOwnership();
}
}
StakingPool.sol 215 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import '@openzeppelin/contracts/access/Ownable.sol';
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import '@openzeppelin/contracts/utils/Context.sol';
import './interfaces/IPoolExtension.sol';
contract StakingPool is Context, Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
uint256 constant MULTIPLIER = 10 ** 36;
uint256 public lockupPeriod;
uint256 public totalStakedUsers;
uint256 public totalSharesDeposited;
address public token;
IPoolExtension public extension;
struct Share {
uint256 amount;
uint256 stakedTime;
}
struct Reward {
uint256 excluded;
uint256 realised;
}
mapping(address => Share) public shares;
mapping(address => Reward) public rewards;
uint256 public rewardsPerShare;
uint256 public totalDistributed;
uint256 public totalRewards;
event Stake(address indexed user, uint256 amount);
event Unstake(address indexed user, uint256 amount);
event ClaimReward(address user);
event DepositRewards(address indexed user, uint256 amountTokens);
event DistributeReward(
address indexed user,
uint256 amount
);
constructor(address _token, uint256 _lockupPeriod) {
token = _token;
lockupPeriod = _lockupPeriod;
}
function stake(uint256 _amount) external nonReentrant {
IERC20(token).safeTransferFrom(_msgSender(), address(this), _amount);
_setShare(_msgSender(), _amount, false);
}
function stakeForWallets(
address[] memory _wallets,
uint256[] memory _amounts
) external nonReentrant {
require(_wallets.length == _amounts.length, 'INSYNC');
uint256 _totalAmount;
for (uint256 _i; _i < _wallets.length; _i++) {
_totalAmount += _amounts[_i];
_setShare(_wallets[_i], _amounts[_i], false);
}
IERC20(token).safeTransferFrom(_msgSender(), address(this), _totalAmount);
}
function unstake(uint256 _amount) external nonReentrant {
IERC20(token).safeTransfer(_msgSender(), _amount);
_setShare(_msgSender(), _amount, true);
}
function _setShare(
address wallet,
uint256 balanceUpdate,
bool isRemoving
) internal {
if (address(extension) != address(0)) {
try extension.setShare(wallet, balanceUpdate, isRemoving) {} catch {}
}
if (isRemoving) {
_removeShares(wallet, balanceUpdate);
emit Unstake(wallet, balanceUpdate);
} else {
_addShares(wallet, balanceUpdate);
emit Stake(wallet, balanceUpdate);
}
}
function _addShares(address wallet, uint256 amount) private {
if (shares[wallet].amount > 0) {
_distributeReward(wallet);
}
uint256 sharesBefore = shares[wallet].amount;
totalSharesDeposited += amount;
shares[wallet].amount += amount;
shares[wallet].stakedTime = block.timestamp;
if (sharesBefore == 0 && shares[wallet].amount > 0) {
totalStakedUsers++;
}
rewards[wallet].excluded = _cumulativeRewards(shares[wallet].amount);
}
function _removeShares(address wallet, uint256 amount) private {
require(
shares[wallet].amount > 0 && amount <= shares[wallet].amount,
'REM: amount'
);
require(
block.timestamp > shares[wallet].stakedTime + lockupPeriod,
'REM: timelock'
);
_distributeReward(wallet);
totalSharesDeposited -= amount;
shares[wallet].amount -= amount;
shares[wallet].stakedTime = block.timestamp;
if (shares[wallet].amount == 0) {
totalStakedUsers--;
}
rewards[wallet].excluded = _cumulativeRewards(shares[wallet].amount);
}
function depositRewards() external payable {
_depositRewards(_msgSender(), msg.value);
}
function _depositRewards(address _wallet, uint256 _amountETH) internal {
require(_amountETH > 0, 'ETH');
require(totalSharesDeposited > 0, 'SHARES');
totalRewards += _amountETH;
rewardsPerShare += (MULTIPLIER * _amountETH) / totalSharesDeposited;
emit DepositRewards(_wallet, _amountETH);
}
function _distributeReward(
address _wallet
) internal {
if (shares[_wallet].amount == 0) {
return;
}
shares[_wallet].stakedTime = block.timestamp; // reset every claim
uint256 _amountWei = getUnpaid(_wallet);
rewards[_wallet].realised += _amountWei;
rewards[_wallet].excluded = _cumulativeRewards(shares[_wallet].amount);
if (_amountWei > 0) {
totalDistributed += _amountWei;
uint256 _balBefore = address(this).balance;
(bool success, ) = payable(_wallet).call{ value: _amountWei }('');
require(success, 'DIST0');
require(address(this).balance >= _balBefore - _amountWei, 'DIST1');
emit DistributeReward(_wallet, _amountWei);
}
}
// function claimReward(
// bool _compound,
// uint256 _compMinTokensToReceive
// ) external nonReentrant {
// _distributeReward(_msgSender(), _compound, _compMinTokensToReceive);
// emit ClaimReward(_msgSender());
// }
function claimRewardAdmin(
address _wallet
) external nonReentrant onlyOwner {
_distributeReward(_wallet);
emit ClaimReward(_wallet);
}
function getUnpaid(address wallet) public view returns (uint256) {
if (shares[wallet].amount == 0) {
return 0;
}
uint256 earnedRewards = _cumulativeRewards(shares[wallet].amount);
uint256 rewardsExcluded = rewards[wallet].excluded;
if (earnedRewards <= rewardsExcluded) {
return 0;
}
return earnedRewards - rewardsExcluded;
}
function _cumulativeRewards(uint256 share) internal view returns (uint256) {
return (share * rewardsPerShare) / MULTIPLIER;
}
function setPoolExtension(IPoolExtension _extension) external onlyOwner {
extension = _extension;
}
function setLockupPeriod(uint256 _seconds) external onlyOwner {
require(_seconds < 365 days, 'lte 1 year');
lockupPeriod = _seconds;
}
function withdrawTokens(address to, uint256 _amount) external onlyOwner {
IERC20 _token = IERC20(token);
_token.safeTransfer(
to,
_amount == 0 ? _token.balanceOf(address(this)) : _amount
);
}
function withdrawETH(address to, uint256 _amount) external onlyOwner {
if (_amount > 0) {
uint256 _balBefore = address(this).balance;
(bool success, ) = payable(to).call{ value: _amount }('');
require(success, 'DIST0');
require(address(this).balance >= _balBefore - _amount, 'DIST1');
emit DistributeReward(to, _amount);
}
}
}
Address.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
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");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
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);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
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);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
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);
}
}
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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;
}
}
Ownable.sol 83 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. 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;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @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 {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_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);
}
}
IPoolExtension.sol 10 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IPoolExtension {
function setShare(
address wallet,
uint256 balanceChange,
bool isRemoving
) external;
}
IERC20.sol 78 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount) external returns (bool);
}
ReentrancyGuard.sol 77 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
SafeERC20.sol 143 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
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));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
IERC20Permit.sol 90 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
Read Contract
adminCanWithdraw 0xc81bf2b1 → bool
getAllPools 0xd88ff1f4 → tuple[]
owner 0x8da5cb5b → address
pools 0xac4afa38 → address, uint256
stakingToken 0x72f702f3 → address
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
claimRewardsBulk 0x3c9fc7cb
uint256 lengthPool
createPool 0x74a110c2
uint256 _lockupSeconds
uint256 _percentage
depositRewards 0x152111f7
No parameters
removePool 0xa38dcbd0
uint256 _idx
removeWithdrawAbility 0x47c31945
No parameters
renounceAllOwnership 0xc88f8f5b
No parameters
renounceOwnership 0x715018a6
No parameters
setExtension 0x1d8092f3
address[] _ext
setLockupPeriods 0x676346ad
uint256[] _seconds
setPercentages 0x1324968d
uint256[] _percentages
transferOwnership 0xf2fde38b
address newOwner
withdrawETHFromPools 0x6247d049
address to
uint256[] _amounts
withdrawFromPools 0x8c5114aa
address to
uint256[] _amounts
Recent Transactions
No transactions found for this address