Address Contract Verified
Address
0xA5dB3faB53eCB34387A180217937b3C772aeCB0F
Balance
0 ETH
Nonce
1
Code Size
10365 bytes
Creator
0xF26e874F...3040 at tx 0x387d6c7a...cc3b59
Indexed Transactions
0
Contract Bytecode
10365 bytes
0x608060405234801561001057600080fd5b50600436106101165760003560e01c80637a1ac61e116100a2578063bbe4491711610071578063bbe4491714610233578063bc197c811461023c578063f23a6e611461024f578063f2fde38b14610262578063fb930e721461027557600080fd5b80637a1ac61e146101f45780638456cb59146102075780638da5cb5b1461020f578063acd2ebf21461022057600080fd5b80631f7678ce116100e95780631f7678ce1461018c578063238ac933146101a35780635c975abb146101ce5780635f3e098a146101d9578063715018a6146101ec57600080fd5b806301ffc9a71461011b578063046f7da214610143578063150b7a021461014d5780631742057314610179575b600080fd5b61012e610129366004612059565b6102b6565b60405190151581526020015b60405180910390f35b61014b6102ed565b005b61016061015b3660046120e8565b6102ff565b6040516001600160e01b0319909116815260200161013a565b61014b61018736600461219c565b61033b565b61019560fe5481565b60405190815260200161013a565b60fd546101b6906001600160a01b031681565b6040516001600160a01b03909116815260200161013a565b60975460ff1661012e565b61014b6101e7366004612205565b610e91565b61014b6110a4565b61014b610202366004612251565b6110b6565b61014b61122e565b6033546001600160a01b03166101b6565b61014b61022e366004612251565b61123e565b61019560ff5481565b61016061024a366004612284565b611299565b61016061025d36600461233f565b6112d8565b61014b6102703660046123b7565b611315565b6101956102833660046123d2565b6001600160a01b039283166000908152610101602090815260408083209490951682529283528381209181529152205490565b60006001600160e01b03198216630a85bd0160e11b14806102e757506001600160e01b03198216630271189760e51b145b92915050565b6102f561138e565b6102fd6113e8565b565b6101005460009060ff16600214610329576040516356fdbe7d60e11b815260040160405180910390fd5b50630a85bd0160e11b95945050505050565b61034361143a565b61034b611493565b6103598333878786866114d9565b158061037157504360ff548461036f9190612424565b105b1561038e5760405162127a7b60eb1b815260040160405180910390fd5b60005b84811015610e3c5760008686838181106103ad576103ad612437565b90506020028101906103bf919061244d565b6103cd9060208101906123b7565b90508686838181106103e1576103e1612437565b90506020028101906103f3919061244d565b61040190604081019061246d565b90506000036106465760005b87878481811061041f5761041f612437565b9050602002810190610431919061244d565b61043f90602081019061246d565b905081101561064057336000908152610101602090815260408083206001600160a01b038616845290915281209089898681811061047f5761047f612437565b9050602002810190610491919061244d565b61049f90602081019061246d565b848181106104af576104af612437565b905060200201358152602001908152602001600020546000036104e5576040516360bea25160e11b815260040160405180910390fd5b336000908152610101602090815260408083206001600160a01b03861684529091528120818a8a8781811061051c5761051c612437565b905060200281019061052e919061244d565b61053c90602081019061246d565b8581811061054c5761054c612437565b90506020020135815260200190815260200160002081905550816001600160a01b03166342842e0e3061057c3390565b8b8b8881811061058e5761058e612437565b90506020028101906105a0919061244d565b6105ae90602081019061246d565b868181106105be576105be612437565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561061557600080fd5b505af1158015610629573d6000803e3d6000fd5b505050508080610638906124b7565b91505061040d565b50610e29565b600287878481811061065a5761065a612437565b905060200281019061066c919061244d565b61067a90602081019061246d565b905010156109f65786868381811061069457610694612437565b90506020028101906106a6919061244d565b6106b490604081019061246d565b60008181106106c5576106c5612437565b9050602002013561010160006106d83390565b6001600160a01b039081168252602080830193909352604091820160009081209186168152925281209089898681811061071457610714612437565b9050602002810190610726919061244d565b61073490602081019061246d565b600081811061074557610745612437565b90506020020135815260200190815260200160002054101561077a576040516360bea25160e11b815260040160405180910390fd5b600087878481811061078e5761078e612437565b90506020028101906107a0919061244d565b6107ae90604081019061246d565b60008181106107bf576107bf612437565b9050602002013561010160006107d23390565b6001600160a01b03908116825260208083019390935260409182016000908120918716815292528120908a8a8781811061080e5761080e612437565b9050602002810190610820919061244d565b61082e90602081019061246d565b600081811061083f5761083f612437565b9050602002013581526020019081526020016000205461085f91906124d0565b905087878481811061087357610873612437565b9050602002810190610885919061244d565b61089390604081019061246d565b60008181106108a4576108a4612437565b9050602002013561010160006108b73390565b6001600160a01b03908116825260208083019390935260409182016000908120918716815292528120908a8a878181106108f3576108f3612437565b9050602002810190610905919061244d565b61091390602081019061246d565b600081811061092457610924612437565b90506020020135815260200190815260200160002081905550816001600160a01b031663f242432a306109543390565b8b8b8881811061096657610966612437565b9050602002810190610978919061244d565b61098690602081019061246d565b600081811061099757610997612437565b90506020020135856040518563ffffffff1660e01b81526004016109be94939291906124e3565b600060405180830381600087803b1580156109d857600080fd5b505af11580156109ec573d6000803e3d6000fd5b5050505050610e29565b6000878784818110610a0a57610a0a612437565b9050602002810190610a1c919061244d565b610a2a90602081019061246d565b905067ffffffffffffffff811115610a4457610a4461251b565b604051908082528060200260200182016040528015610a6d578160200160208202803683370190505b50905060005b888885818110610a8557610a85612437565b9050602002810190610a97919061244d565b610aa590602081019061246d565b9050811015610d9057888885818110610ac057610ac0612437565b9050602002810190610ad2919061244d565b610ae090604081019061246d565b82818110610af057610af0612437565b905060200201356101016000610b033390565b6001600160a01b03908116825260208083019390935260409182016000908120918816815292528120908b8b88818110610b3f57610b3f612437565b9050602002810190610b51919061244d565b610b5f90602081019061246d565b85818110610b6f57610b6f612437565b905060200201358152602001908152602001600020541015610ba4576040516360bea25160e11b815260040160405180910390fd5b888885818110610bb657610bb6612437565b9050602002810190610bc8919061244d565b610bd690604081019061246d565b82818110610be657610be6612437565b905060200201356101016000610bf93390565b6001600160a01b03908116825260208083019390935260409182016000908120918816815292528120908b8b88818110610c3557610c35612437565b9050602002810190610c47919061244d565b610c5590602081019061246d565b85818110610c6557610c65612437565b90506020020135815260200190815260200160002054610c8591906124d0565b828281518110610c9757610c97612437565b602002602001018181525050888885818110610cb557610cb5612437565b9050602002810190610cc7919061244d565b610cd590604081019061246d565b82818110610ce557610ce5612437565b905060200201356101016000610cf83390565b6001600160a01b03908116825260208083019390935260409182016000908120918816815292528120908b8b88818110610d3457610d34612437565b9050602002810190610d46919061244d565b610d5490602081019061246d565b85818110610d6457610d64612437565b905060200201358152602001908152602001600020819055508080610d88906124b7565b915050610a73565b506001600160a01b038216632eb2c2d630338b8b88818110610db457610db4612437565b9050602002810190610dc6919061244d565b610dd490602081019061246d565b866040518663ffffffff1660e01b8152600401610df5959493929190612563565b600060405180830381600087803b158015610e0f57600080fd5b505af1158015610e23573d6000803e3d6000fd5b50505050505b5080610e34816124b7565b915050610391565b50336001600160a01b03167f011673439234c6c4ab1bbaf0bb213c849faa0badecf357e8257819c9a3d68e138686604051610e789291906126e8565b60405180910390a2610e8a6001606555565b5050505050565b610e9961143a565b610ea1611493565b60fe54811015610ec4576040516311453d1560e11b815260040160405180910390fd5b816000819003610ee75760405163de9fe3cd60e01b815260040160405180910390fd5b60005b8181101561104e57848482818110610f0457610f04612437565b9050602002810190610f16919061244d565b610f2490604081019061246d565b9050600003610f9e57610f99858583818110610f4257610f42612437565b9050602002810190610f54919061244d565b610f629060208101906123b7565b868684818110610f7457610f74612437565b9050602002810190610f86919061244d565b610f9490602081019061246d565b6117ab565b61103c565b61103c858583818110610fb357610fb3612437565b9050602002810190610fc5919061244d565b610fd39060208101906123b7565b868684818110610fe557610fe5612437565b9050602002810190610ff7919061244d565b61100590602081019061246d565b88888681811061101757611017612437565b9050602002810190611029919061244d565b61103790604081019061246d565b6118e4565b80611046816124b7565b915050610eea565b50336001600160a01b03167f32e0a216c38657fb69ac38b36348bcab9651e43af587bf706ba5e7f0c7f712d185858560405161108c93929190612704565b60405180910390a25061109f6001606555565b505050565b6110ac61138e565b6102fd6000611b71565b600054610100900460ff16158080156110d65750600054600160ff909116105b806110f05750303b1580156110f0575060005460ff166001145b6111585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801561117b576000805461ff0019166101001790555b611183611bc3565b61118b611bf3565b611193611c1a565b6111d7604051806040016040528060058152602001640908a9892b60db1b81525060405180604001604052806005815260200164302e302e3160d81b815250611c4d565b6111e284848461123e565b8015611228576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b61123661138e565b6102fd611c8e565b61124661138e565b81158015611252575080155b156112705760405163209d6cb160e21b815260040160405180910390fd5b60fd80546001600160a01b0319166001600160a01b03949094169390931790925560fe5560ff55565b6101005460009060ff166002146112c3576040516356fdbe7d60e11b815260040160405180910390fd5b5063bc197c8160e01b98975050505050505050565b6101005460009060ff16600214611302576040516356fdbe7d60e11b815260040160405180910390fd5b5063f23a6e6160e01b9695505050505050565b61131d61138e565b6001600160a01b0381166113825760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161114f565b61138b81611b71565b50565b6033546001600160a01b031633146102fd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161114f565b6113f0611ccb565b6097805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60026065540361148c5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161114f565b6002606555565b60975460ff16156102fd5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161114f565b6000808467ffffffffffffffff8111156114f5576114f561251b565b60405190808252806020026020018201604052801561151e578160200160208202803683370190505b50905060005b858110156116a8577fdf26e40bc1f135d6b80b651a07ad65f2a160452b59b747f03bc854090bc5266087878381811061155f5761155f612437565b9050602002810190611571919061244d565b61157f9060208101906123b7565b88888481811061159157611591612437565b90506020028101906115a3919061244d565b6115b190602081019061246d565b6040516020016115c2929190612728565b604051602081830303815290604052805190602001208989858181106115ea576115ea612437565b90506020028101906115fc919061244d565b61160a90604081019061246d565b60405160200161161b929190612728565b6040516020818303038152906040528051906020012060405160200161166394939291909384526001600160a01b039290921660208401526040830152606082015260800190565b6040516020818303038152906040528051906020012082828151811061168b5761168b612437565b6020908102919091010152806116a0816124b7565b915050611524565b5060007f2c85c132c8952239fa3c963700331973245f24d77971c4d8473ceaff6f3c22588989846040516020016116df9190612751565b60408051601f198184030181528282528051602091820120908301959095528101929092526001600160a01b03166060820152608081019190915260a001604051602081830303815290604052805190602001209050600061174082611d14565b905060006117848288888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611d6292505050565b60fd546001600160a01b039081169116149b9a5050505050505050505050565b6001606555565b8260005b82811015610e8a57610100805460ff191660021790556001600160a01b0382166342842e0e6117db3390565b308787868181106117ee576117ee612437565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561184557600080fd5b505af1158015611859573d6000803e3d6000fd5b5050610100805460ff1916600190811790915591506101019050600061187c3390565b6001600160a01b03908116825260208083019390935260409182016000908120918a16815292528120908686858181106118b8576118b8612437565b9050602002013581526020019081526020016000208190555080806118dc906124b7565b9150506117af565b846002841015611a3457610100805460ff191660021790556001600160a01b03811663f242432a6119123390565b308888600081811061192657611926612437565b905060200201358787600081811061194057611940612437565b905060200201356040518563ffffffff1660e01b815260040161196694939291906124e3565b600060405180830381600087803b15801561198057600080fd5b505af1158015611994573d6000803e3d6000fd5b5050610100805460ff1916600117905550839050826000816119b8576119b8612437565b9050602002013561010160006119cb3390565b6001600160a01b03908116825260208083019390935260409182016000908120918b168152925281209087878281611a0557611a05612437565b9050602002013581526020019081526020016000206000828254611a299190612424565b90915550611b699050565b610100805460ff191660021790556001600160a01b038116632eb2c2d6611a583390565b30888888886040518763ffffffff1660e01b8152600401611a7e96959493929190612787565b600060405180830381600087803b158015611a9857600080fd5b505af1158015611aac573d6000803e3d6000fd5b5050610100805460ff1916600117905550600090505b84811015611b6757838382818110611adc57611adc612437565b905060200201356101016000611aef3390565b6001600160a01b03908116825260208083019390935260409182016000908120918c1681529252812090888885818110611b2b57611b2b612437565b9050602002013581526020019081526020016000206000828254611b4f9190612424565b90915550819050611b5f816124b7565b915050611ac2565b505b505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611bea5760405162461bcd60e51b815260040161114f906127e6565b6102fd33611b71565b600054610100900460ff166117a45760405162461bcd60e51b815260040161114f906127e6565b600054610100900460ff16611c415760405162461bcd60e51b815260040161114f906127e6565b6097805460ff19169055565b600054610100900460ff16611c745760405162461bcd60e51b815260040161114f906127e6565b81516020928301208151919092012060c99190915560ca55565b611c96611493565b6097805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861141d3390565b60975460ff166102fd5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161114f565b60006102e7611d21611d86565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000611d718585611e06565b91509150611d7e81611e4b565b509392505050565b6000611e017f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611db560c95490565b60ca546040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b905090565b6000808251604103611e3c5760208301516040840151606085015160001a611e3087828585611f95565b94509450505050611e44565b506000905060025b9250929050565b6000816004811115611e5f57611e5f612831565b03611e675750565b6001816004811115611e7b57611e7b612831565b03611ec85760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161114f565b6002816004811115611edc57611edc612831565b03611f295760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161114f565b6003816004811115611f3d57611f3d612831565b0361138b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161114f565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611fcc5750600090506003612050565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612020573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661204957600060019250925050612050565b9150600090505b94509492505050565b60006020828403121561206b57600080fd5b81356001600160e01b03198116811461208357600080fd5b9392505050565b80356001600160a01b03811681146120a157600080fd5b919050565b60008083601f8401126120b857600080fd5b50813567ffffffffffffffff8111156120d057600080fd5b602083019150836020828501011115611e4457600080fd5b60008060008060006080868803121561210057600080fd5b6121098661208a565b94506121176020870161208a565b935060408601359250606086013567ffffffffffffffff81111561213a57600080fd5b612146888289016120a6565b969995985093965092949392505050565b60008083601f84011261216957600080fd5b50813567ffffffffffffffff81111561218157600080fd5b6020830191508360208260051b8501011115611e4457600080fd5b6000806000806000606086880312156121b457600080fd5b853567ffffffffffffffff808211156121cc57600080fd5b6121d889838a01612157565b90975095506020880135945060408801359150808211156121f857600080fd5b50612146888289016120a6565b60008060006040848603121561221a57600080fd5b833567ffffffffffffffff81111561223157600080fd5b61223d86828701612157565b909790965060209590950135949350505050565b60008060006060848603121561226657600080fd5b61226f8461208a565b95602085013595506040909401359392505050565b60008060008060008060008060a0898b0312156122a057600080fd5b6122a98961208a565b97506122b760208a0161208a565b9650604089013567ffffffffffffffff808211156122d457600080fd5b6122e08c838d01612157565b909850965060608b01359150808211156122f957600080fd5b6123058c838d01612157565b909650945060808b013591508082111561231e57600080fd5b5061232b8b828c016120a6565b999c989b5096995094979396929594505050565b60008060008060008060a0878903121561235857600080fd5b6123618761208a565b955061236f6020880161208a565b94506040870135935060608701359250608087013567ffffffffffffffff81111561239957600080fd5b6123a589828a016120a6565b979a9699509497509295939492505050565b6000602082840312156123c957600080fd5b6120838261208a565b6000806000606084860312156123e757600080fd5b6123f08461208a565b92506123fe6020850161208a565b9150604084013590509250925092565b634e487b7160e01b600052601160045260246000fd5b808201808211156102e7576102e761240e565b634e487b7160e01b600052603260045260246000fd5b60008235605e1983360301811261246357600080fd5b9190910192915050565b6000808335601e1984360301811261248457600080fd5b83018035915067ffffffffffffffff82111561249f57600080fd5b6020019150600581901b3603821315611e4457600080fd5b6000600182016124c9576124c961240e565b5060010190565b818103818111156102e7576102e761240e565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052604160045260246000fd5b81835260006001600160fb1b0383111561254a57600080fd5b8260051b80836020870137939093016020019392505050565b600060018060a01b03808816835260208188168185015260a0604085015261258f60a085018789612531565b8481036060860152855180825282870193509082019060005b818110156125c4578451835293830193918301916001016125a8565b505084810360808601526000815281810193505050509695505050505050565b6000808335601e198436030181126125fb57600080fd5b830160208101925035905067ffffffffffffffff81111561261b57600080fd5b8060051b3603821315611e4457600080fd5b81835260006020808501808196508560051b81019150846000805b888110156126da578385038a528235605e19893603018112612668578283fd5b880160606001600160a01b0361267d8361208a565b16875261268c888301836125e4565b828a8a015261269e838a018284612531565b9250505060406126b0818401846125e4565b9350888303828a01526126c4838583612531565b9d8a019d98505050938701935050600101612648565b509298975050505050505050565b6020815260006126fc60208301848661262d565b949350505050565b60408152600061271860408301858761262d565b9050826020830152949350505050565b60006001600160fb1b0383111561273e57600080fd5b8260051b80858437919091019392505050565b815160009082906020808601845b8381101561277b5781518552938201939082019060010161275f565b50929695505050505050565b6001600160a01b0387811682528616602082015260a0604082018190526000906127b49083018688612531565b82810360608401526127c7818587612531565b8381036080909401939093525050600081526020019695505050505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052602160045260246000fdfea26469706673582212208819677719cdb3ccb0ea8f05c481560744b193112b4f28b685f172001de56e0564736f6c63430008130033
Verified Source Code Full Match
Compiler: v0.8.19+commit.7dd6d404
EVM: paris
Optimization: Yes (200 runs)
HelixStake.sol 393 lines
// SPDX-License-Identifier: PRIVATE
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/interfaces/IERC165Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol";
// TOKEN
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
error HelixStake__ConfigError();
error HelixStake__NoDirectTransfer();
error HelixStake__StakeNotExists();
error HelixStake__NotValidRequest();
error HelixStake__StackNoToken();
error HelixStake__PeriodTooShort();
// error HelixStake__NoPermission();
contract HelixStake is
Initializable,
OwnableUpgradeable,
ReentrancyGuardUpgradeable,
PausableUpgradeable,
EIP712Upgradeable,
IERC165Upgradeable,
IERC721ReceiverUpgradeable,
IERC1155ReceiverUpgradeable
{
/*
HELIX Legal Terms
1. HELIX Terms of Service [https://helixmetaverse.com/tos/]
2. HELIX Privacy Policy [https://helixmetaverse.com/privacy/]
*/
/// @dev Emitted when tokens are staked.
event TokensStaked(
address indexed staker,
StakeRequest[] requests,
uint256 timePeriod
);
/// @dev Emitted when a set of staked token are withdrawn.
event TokensWithdrawn(address indexed staker, StakeRequest[] requests);
/// @dev WITHDRAW HASH
bytes32 private constant WITHDRAW_HASH =
keccak256(
"withdraw(uint256 blockNum,address user,StakeRequest[] reqs)StakeRequest(address tokenAddress,uint256[] tokenIds,uint256[] amounts)"
);
/// @dev Request HASH
bytes32 private constant REQ_HASH =
keccak256(
"StakeRequest(address tokenAddress,uint256[] tokenIds,uint256[] amounts)"
);
/// @dev signer
address public signer;
/// @dev The minimal stack time
uint256 public minStakeTime;
/// @dev the valid time for request
uint256 public validTime;
/// @dev Flag to check direct transfers of staking tokens.
uint8 internal isStaking = 1;
/// @dev Stacking Request
struct StakeRequest {
address tokenAddress;
uint256[] tokenIds;
// 0 length it is a ERC721, ERC1155 otherwise
uint256[] amounts;
}
/// @dev staking data
mapping(address => mapping(address => mapping(uint256 => uint256)))
private _stake;
/// @dev Initiliazes the contract, like a constructor.
function initialize(
address _signer,
uint256 _minStakeTime,
uint256 _validTime
) public initializer {
__Ownable_init_unchained();
__ReentrancyGuard_init_unchained();
__Pausable_init_unchained();
__EIP712_init_unchained("HELIX", "0.0.1");
setConfig(_signer, _minStakeTime, _validTime);
}
/// @dev update stacking configuration
function setConfig(
address _signer,
uint256 _minStakeTime,
uint256 _validTime
) public onlyOwner {
if (_minStakeTime <= 0 && _validTime <= 0) {
revert HelixStake__ConfigError();
}
signer = _signer;
minStakeTime = _minStakeTime;
validTime = _validTime;
}
function pause() external onlyOwner {
_pause();
}
function resume() external onlyOwner {
_unpause();
}
/// @dev stake
function stake(
StakeRequest[] calldata _requests,
uint256 _timePeriod
) external nonReentrant whenNotPaused {
if (_timePeriod < minStakeTime) revert HelixStake__PeriodTooShort();
uint256 len = _requests.length;
if (len == 0) revert HelixStake__StackNoToken();
// check period
// block.number + _timePeriod;
// stack
for (uint256 i = 0; i < len; i++) {
if (_requests[i].amounts.length == 0) {
_stakeERC721(_requests[i].tokenAddress, _requests[i].tokenIds);
} else {
_stakeERC1155(
_requests[i].tokenAddress,
_requests[i].tokenIds,
_requests[i].amounts
);
}
}
emit TokensStaked(_stakeSender(), _requests, _timePeriod);
}
/// @dev withdraw
function withdraw(
StakeRequest[] calldata _req,
uint256 blockNum,
bytes calldata _sign
) external nonReentrant whenNotPaused {
if (
!_checkSignature(blockNum, _stakeSender(), _req, _sign) ||
blockNum + validTime < block.number
) revert HelixStake__NotValidRequest();
for (uint256 i = 0; i < _req.length; i++) {
address tokenAddress = _req[i].tokenAddress;
if (_req[i].amounts.length == 0) {
// ERC721
for (uint256 j = 0; j < _req[i].tokenIds.length; j++) {
// check if user staked token
if (
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[j]
] == 0
) revert HelixStake__StakeNotExists();
// clear if user staked
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[j]
] = 0;
// transfer token
IERC721(tokenAddress).safeTransferFrom(
address(this),
_stakeSender(),
_req[i].tokenIds[j]
);
}
} else {
// ERC1155
if (_req[i].tokenIds.length < 2) {
// check if user staked token
if (
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[0]
] < _req[i].amounts[0]
) revert HelixStake__StakeNotExists();
// clear if user staked
uint256 amount = _stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[0]
] - _req[i].amounts[0];
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[0]
] = _req[i].amounts[0];
IERC1155(tokenAddress).safeTransferFrom(
address(this),
_stakeSender(),
_req[i].tokenIds[0],
amount,
""
);
} else {
uint256[] memory amounts = new uint256[](
_req[i].tokenIds.length
);
for (uint256 j = 0; j < _req[i].tokenIds.length; j++) {
// check if user staked token
if (
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[j]
] < _req[i].amounts[j]
) revert HelixStake__StakeNotExists();
// clear if user staked
amounts[j] =
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[j]
] -
_req[i].amounts[j];
_stake[_stakeSender()][tokenAddress][
_req[i].tokenIds[j]
] = _req[i].amounts[j];
}
IERC1155(tokenAddress).safeBatchTransferFrom(
address(this),
_stakeSender(),
_req[i].tokenIds,
amounts,
""
);
}
}
}
emit TokensWithdrawn(_stakeSender(), _req);
}
function getStaked(
address _addr,
address _tokenAddr,
uint256 tokenId
) external view returns (uint256) {
return _stake[_addr][_tokenAddr][tokenId];
}
/*///////////////////////////////////////////////////////////////
ERC 165 / 721 / 1155 logic
//////////////////////////////////////////////////////////////*/
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external view returns (bytes4) {
if (isStaking != 2) revert HelixStake__NoDirectTransfer();
return this.onERC721Received.selector;
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes calldata
) external view returns (bytes4) {
if (isStaking != 2) revert HelixStake__NoDirectTransfer();
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external view returns (bytes4) {
if (isStaking != 2) revert HelixStake__NoDirectTransfer();
return this.onERC1155BatchReceived.selector;
}
function supportsInterface(
bytes4 interfaceId
) external pure returns (bool) {
return
interfaceId == type(IERC721ReceiverUpgradeable).interfaceId ||
interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId;
}
/*///////////////////////////////////////////////////////////////
Internal function
//////////////////////////////////////////////////////////////*/
function _stakeERC721(
address _tokenAddr,
uint256[] calldata _tokenIds
) internal {
IERC721 token = IERC721(_tokenAddr);
for (uint256 i = 0; i < _tokenIds.length; i++) {
// if (
// token.ownerOf(_tokenIds[i]) != _stakeSender() ||
// (token.getApproved(_tokenIds[i]) != address(this) &&
// !token.isApprovedForAll(_stakeSender(), address(this)))
// ) revert HelixStake__NoPermission();
isStaking = 2;
token.safeTransferFrom(_stakeSender(), address(this), _tokenIds[i]);
isStaking = 1;
_stake[_stakeSender()][_tokenAddr][_tokenIds[i]] = 1;
}
}
function _stakeERC1155(
address _tokenAddr,
uint256[] calldata _tokenIds,
uint256[] calldata _amounts
) internal {
IERC1155 token = IERC1155(_tokenAddr);
if (_tokenIds.length < 2) {
// if (
// token.balanceOf(_stakeSender(), _tokenIds[0]) < _amounts[0] ||
// !token.isApprovedForAll(_stakeSender(), address(this))
// ) revert HelixStake__NoPermission();
isStaking = 2;
token.safeTransferFrom(
_stakeSender(),
address(this),
_tokenIds[0],
_amounts[0],
""
);
isStaking = 1;
_stake[_stakeSender()][_tokenAddr][_tokenIds[0]] += _amounts[0];
} else {
isStaking = 2;
token.safeBatchTransferFrom(
_stakeSender(),
address(this),
_tokenIds,
_amounts,
""
);
isStaking = 1;
for (uint256 i = 0; i < _tokenIds.length; i++) {
_stake[_stakeSender()][_tokenAddr][_tokenIds[i]] += _amounts[i];
}
}
}
/// @dev check signature
function _checkSignature(
uint256 blockNum,
address _sender,
StakeRequest[] calldata _reqs,
bytes calldata _sign
) internal view returns (bool) {
bytes32[] memory reqHash = new bytes32[](_reqs.length);
for (uint256 i = 0; i < _reqs.length; i++) {
reqHash[i] = keccak256(
abi.encode(
REQ_HASH,
_reqs[i].tokenAddress,
keccak256(abi.encodePacked(_reqs[i].tokenIds)),
keccak256(abi.encodePacked(_reqs[i].amounts))
)
);
}
bytes32 hash = keccak256(
abi.encode(
WITHDRAW_HASH,
blockNum,
_sender,
keccak256(abi.encodePacked(reqHash))
)
);
bytes32 digest = _hashTypedDataV4(hash);
address signer_ = ECDSAUpgradeable.recover(digest, _sign);
return signer_ == signer;
}
/// @dev Exposes the ability to override the msg sender -- support ERC2771.
function _stakeSender() internal virtual returns (address) {
return msg.sender;
}
}
IERC721.sol 145 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @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`.
*
* 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;
/**
* @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 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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* 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 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 the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @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);
}
IERC1155.sol 125 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @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);
}
AddressUpgradeable.sol 219 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @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
* ====
*
* [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://diligence.consensys.net/posts/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.5.11/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 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);
}
}
}
ContextUpgradeable.sol 37 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
StringsUpgradeable.sol 70 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/MathUpgradeable.sol";
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = MathUpgradeable.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, MathUpgradeable.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
OwnableUpgradeable.sol 95 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_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 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 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);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
Initializable.sol 165 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
MathUpgradeable.sol 345 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
PausableUpgradeable.sol 117 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
IERC165Upgradeable.sol 6 lines
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165Upgradeable.sol";
ReentrancyGuardUpgradeable.sol 81 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @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 ReentrancyGuardUpgradeable is Initializable {
// 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;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_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 This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
ECDSAUpgradeable.sol 213 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../StringsUpgradeable.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
EIP712Upgradeable.sol 121 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)
pragma solidity ^0.8.0;
import "./ECDSAUpgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
*
* The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
* thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
* they need in their contracts using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* _Available since v3.4._
*
* @custom:storage-size 52
*/
abstract contract EIP712Upgradeable is Initializable {
/* solhint-disable var-name-mixedcase */
bytes32 private _HASHED_NAME;
bytes32 private _HASHED_VERSION;
bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
/* solhint-enable var-name-mixedcase */
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/
function __EIP712_init(string memory name, string memory version) internal onlyInitializing {
__EIP712_init_unchained(name, version);
}
function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
}
/**
* @dev Returns the domain separator for the current chain.
*/
function _domainSeparatorV4() internal view returns (bytes32) {
return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev The hash of the name parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712NameHash() internal virtual view returns (bytes32) {
return _HASHED_NAME;
}
/**
* @dev The hash of the version parameter for the EIP712 domain.
*
* NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
* are a concern.
*/
function _EIP712VersionHash() internal virtual view returns (bytes32) {
return _HASHED_VERSION;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
IERC165Upgradeable.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @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 IERC165Upgradeable {
/**
* @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);
}
IERC721ReceiverUpgradeable.sol 27 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721ReceiverUpgradeable {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
IERC1155ReceiverUpgradeable.sol 58 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165Upgradeable.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155ReceiverUpgradeable is IERC165Upgradeable {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
Read Contract
getStaked 0xfb930e72 → uint256
minStakeTime 0x1f7678ce → uint256
onERC1155BatchReceived 0xbc197c81 → bytes4
onERC1155Received 0xf23a6e61 → bytes4
onERC721Received 0x150b7a02 → bytes4
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
signer 0x238ac933 → address
supportsInterface 0x01ffc9a7 → bool
validTime 0xbbe44917 → uint256
Write Contract 8 functions
These functions modify contract state and require a wallet transaction to execute.
initialize 0x7a1ac61e
address _signer
uint256 _minStakeTime
uint256 _validTime
pause 0x8456cb59
No parameters
renounceOwnership 0x715018a6
No parameters
resume 0x046f7da2
No parameters
setConfig 0xacd2ebf2
address _signer
uint256 _minStakeTime
uint256 _validTime
stake 0xdb27d23a
tuple[] _requests
uint256 _timePeriod
transferOwnership 0xf2fde38b
address newOwner
withdraw 0xd03dc306
tuple[] _req
uint256 blockNum
bytes _sign
Recent Transactions
No transactions found for this address