diff --git a/src/UniStaker.sol b/src/UniStaker.sol index babdc1a..0e6edb6 100644 --- a/src/UniStaker.sol +++ b/src/UniStaker.sol @@ -83,6 +83,9 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @notice Thrown if a caller attempts to specify address zero for certain designated addresses. error UniStaker__InvalidAddress(); + /// @notice Thrown when an onBehalf method is called with a deadline that has expired. + error UniStaker__ExpiredSignature(); + /// @notice Thrown if a caller supplies an invalid signature to a method that requires one. error UniStaker__InvalidSignature(); @@ -100,25 +103,27 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @notice Type hash used when encoding data for `stakeOnBehalf` calls. bytes32 public constant STAKE_TYPEHASH = keccak256( - "Stake(uint256 amount,address delegatee,address beneficiary,address depositor,uint256 nonce)" + "Stake(uint256 amount,address delegatee,address beneficiary,address depositor,uint256 nonce,uint256 deadline)" ); /// @notice Type hash used when encoding data for `stakeMoreOnBehalf` calls. - bytes32 public constant STAKE_MORE_TYPEHASH = - keccak256("StakeMore(uint256 depositId,uint256 amount,address depositor,uint256 nonce)"); + bytes32 public constant STAKE_MORE_TYPEHASH = keccak256( + "StakeMore(uint256 depositId,uint256 amount,address depositor,uint256 nonce,uint256 deadline)" + ); /// @notice Type hash used when encoding data for `alterDelegateeOnBehalf` calls. bytes32 public constant ALTER_DELEGATEE_TYPEHASH = keccak256( - "AlterDelegatee(uint256 depositId,address newDelegatee,address depositor,uint256 nonce)" + "AlterDelegatee(uint256 depositId,address newDelegatee,address depositor,uint256 nonce,uint256 deadline)" ); /// @notice Type hash used when encoding data for `alterBeneficiaryOnBehalf` calls. bytes32 public constant ALTER_BENEFICIARY_TYPEHASH = keccak256( - "AlterBeneficiary(uint256 depositId,address newBeneficiary,address depositor,uint256 nonce)" + "AlterBeneficiary(uint256 depositId,address newBeneficiary,address depositor,uint256 nonce,uint256 deadline)" ); /// @notice Type hash used when encoding data for `withdrawOnBehalf` calls. - bytes32 public constant WITHDRAW_TYPEHASH = - keccak256("Withdraw(uint256 depositId,uint256 amount,address depositor,uint256 nonce)"); + bytes32 public constant WITHDRAW_TYPEHASH = keccak256( + "Withdraw(uint256 depositId,uint256 amount,address depositor,uint256 nonce,uint256 deadline)" + ); /// @notice Type hash used when encoding data for `claimRewardOnBehalf` calls. bytes32 public constant CLAIM_REWARD_TYPEHASH = - keccak256("ClaimReward(address beneficiary,uint256 nonce)"); + keccak256("ClaimReward(address beneficiary,uint256 nonce,uint256 deadline)"); /// @notice ERC20 token in which rewards are denominated and distributed. IERC20 public immutable REWARD_TOKEN; @@ -309,6 +314,7 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @param _delegatee Address to assign the governance voting weight of the staked tokens. /// @param _beneficiary Address that will accrue rewards for this stake. /// @param _depositor Address of the user on whose behalf this stake is being made. + /// @param _deadline The timestamp at which the signature should expire. /// @param _signature Signature of the user authorizing this stake. /// @return _depositId Unique identifier for this deposit. /// @dev Neither the delegatee nor the beneficiary may be the zero address. @@ -317,14 +323,22 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { address _delegatee, address _beneficiary, address _depositor, + uint256 _deadline, bytes memory _signature ) external returns (DepositIdentifier _depositId) { + _revertIfPastDeadline(_deadline); _revertIfSignatureIsNotValidNow( _depositor, _hashTypedDataV4( keccak256( abi.encode( - STAKE_TYPEHASH, _amount, _delegatee, _beneficiary, _depositor, _useNonce(_depositor) + STAKE_TYPEHASH, + _amount, + _delegatee, + _beneficiary, + _depositor, + _useNonce(_depositor), + _deadline ) ) ), @@ -378,21 +392,25 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @param _depositId Unique identifier of the deposit to which stake will be added. /// @param _amount Quantity of stake to be added. /// @param _depositor Address of the user on whose behalf this stake is being made. + /// @param _deadline The timestamp at which the signature should expire. /// @param _signature Signature of the user authorizing this stake. function stakeMoreOnBehalf( DepositIdentifier _depositId, uint256 _amount, address _depositor, + uint256 _deadline, bytes memory _signature ) external { Deposit storage deposit = deposits[_depositId]; _revertIfNotDepositOwner(deposit, _depositor); - + _revertIfPastDeadline(_deadline); _revertIfSignatureIsNotValidNow( _depositor, _hashTypedDataV4( keccak256( - abi.encode(STAKE_MORE_TYPEHASH, _depositId, _amount, _depositor, _useNonce(_depositor)) + abi.encode( + STAKE_MORE_TYPEHASH, _depositId, _amount, _depositor, _useNonce(_depositor), _deadline + ) ) ), _signature @@ -418,23 +436,30 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @param _depositId Unique identifier of the deposit which will have its delegatee altered. /// @param _newDelegatee Address of the new governance delegate. /// @param _depositor Address of the user on whose behalf this stake is being made. + /// @param _deadline The timestamp at which the signature should expire. /// @param _signature Signature of the user authorizing this stake. /// @dev The new delegatee may not be the zero address. function alterDelegateeOnBehalf( DepositIdentifier _depositId, address _newDelegatee, address _depositor, + uint256 _deadline, bytes memory _signature ) external { Deposit storage deposit = deposits[_depositId]; _revertIfNotDepositOwner(deposit, _depositor); - + _revertIfPastDeadline(_deadline); _revertIfSignatureIsNotValidNow( _depositor, _hashTypedDataV4( keccak256( abi.encode( - ALTER_DELEGATEE_TYPEHASH, _depositId, _newDelegatee, _depositor, _useNonce(_depositor) + ALTER_DELEGATEE_TYPEHASH, + _depositId, + _newDelegatee, + _depositor, + _useNonce(_depositor), + _deadline ) ) ), @@ -461,17 +486,19 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @param _depositId Unique identifier of the deposit which will have its beneficiary altered. /// @param _newBeneficiary Address of the new rewards beneficiary. /// @param _depositor Address of the user on whose behalf this stake is being made. + /// @param _deadline The timestamp at which the signature should expire. /// @param _signature Signature of the user authorizing this stake. /// @dev The new beneficiary may not be the zero address. function alterBeneficiaryOnBehalf( DepositIdentifier _depositId, address _newBeneficiary, address _depositor, + uint256 _deadline, bytes memory _signature ) external { Deposit storage deposit = deposits[_depositId]; _revertIfNotDepositOwner(deposit, _depositor); - + _revertIfPastDeadline(_deadline); _revertIfSignatureIsNotValidNow( _depositor, _hashTypedDataV4( @@ -481,7 +508,8 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { _depositId, _newBeneficiary, _depositor, - _useNonce(_depositor) + _useNonce(_depositor), + _deadline ) ) ), @@ -507,22 +535,26 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @param _depositId Unique identifier of the deposit from which stake will be withdrawn. /// @param _amount Quantity of staked token to withdraw. /// @param _depositor Address of the user on whose behalf this stake is being made. + /// @param _deadline The timestamp at which the signature should expire. /// @param _signature Signature of the user authorizing this stake. /// @dev Stake is withdrawn to the deposit owner's account. function withdrawOnBehalf( DepositIdentifier _depositId, uint256 _amount, address _depositor, + uint256 _deadline, bytes memory _signature ) external { Deposit storage deposit = deposits[_depositId]; _revertIfNotDepositOwner(deposit, _depositor); - + _revertIfPastDeadline(_deadline); _revertIfSignatureIsNotValidNow( _depositor, _hashTypedDataV4( keccak256( - abi.encode(WITHDRAW_TYPEHASH, _depositId, _amount, _depositor, _useNonce(_depositor)) + abi.encode( + WITHDRAW_TYPEHASH, _depositId, _amount, _depositor, _useNonce(_depositor), _deadline + ) ) ), _signature @@ -540,12 +572,18 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { /// @notice Claim earned reward tokens for a beneficiary, using a signature to validate the /// beneficiary's intent. Tokens are sent to the beneficiary. /// @param _beneficiary Address of the beneficiary who will receive the reward. + /// @param _deadline The timestamp at which the signature should expire. /// @param _signature Signature of the beneficiary authorizing this reward claim. - function claimRewardOnBehalf(address _beneficiary, bytes memory _signature) external { + function claimRewardOnBehalf(address _beneficiary, uint256 _deadline, bytes memory _signature) + external + { + _revertIfPastDeadline(_deadline); _revertIfSignatureIsNotValidNow( _beneficiary, _hashTypedDataV4( - keccak256(abi.encode(CLAIM_REWARD_TYPEHASH, _beneficiary, _useNonce(_beneficiary))) + keccak256( + abi.encode(CLAIM_REWARD_TYPEHASH, _beneficiary, _useNonce(_beneficiary), _deadline) + ) ), _signature ); @@ -795,6 +833,10 @@ contract UniStaker is INotifiableRewardReceiver, Multicall, EIP712, Nonces { if (_account == address(0)) revert UniStaker__InvalidAddress(); } + function _revertIfPastDeadline(uint256 _deadline) internal view { + if (block.timestamp > _deadline) revert UniStaker__ExpiredSignature(); + } + /// @notice Internal helper method which reverts with UniStaker__InvalidSignature if the signature /// is invalid. /// @param _signer Address of the signer. diff --git a/test/UniStaker.t.sol b/test/UniStaker.t.sol index 89124f8..ce8fadb 100644 --- a/test/UniStaker.t.sol +++ b/test/UniStaker.t.sol @@ -806,9 +806,11 @@ contract StakeOnBehalf is UniStakerTest { uint256 _depositAmount, address _delegatee, address _beneficiary, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _depositAmount = _boundMintAmount(_depositAmount); @@ -828,7 +830,8 @@ contract StakeOnBehalf is UniStakerTest { _delegatee, _beneficiary, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -837,8 +840,9 @@ contract StakeOnBehalf is UniStakerTest { bytes memory _signature = _sign(_depositorPrivateKey, _messageHash); vm.prank(_sender); - UniStaker.DepositIdentifier _depositId = - uniStaker.stakeOnBehalf(_depositAmount, _delegatee, _beneficiary, _depositor, _signature); + UniStaker.DepositIdentifier _depositId = uniStaker.stakeOnBehalf( + _depositAmount, _delegatee, _beneficiary, _depositor, _deadline, _signature + ); UniStaker.Deposit memory _deposit = _fetchDeposit(_depositId); @@ -855,10 +859,12 @@ contract StakeOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, uint256 _currentNonce, - uint256 _suppliedNonce + uint256 _suppliedNonce, + uint256 _deadline ) public { vm.assume(_currentNonce != _suppliedNonce); vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _depositAmount = _boundMintAmount(_depositAmount); @@ -878,7 +884,8 @@ contract StakeOnBehalf is UniStakerTest { _delegatee, _beneficiary, _depositor, - _suppliedNonce + _suppliedNonce, + _deadline ) ); @@ -888,7 +895,9 @@ contract StakeOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.stakeOnBehalf(_depositAmount, _delegatee, _beneficiary, _depositor, _signature); + uniStaker.stakeOnBehalf( + _depositAmount, _delegatee, _beneficiary, _depositor, _deadline, _signature + ); } function testFuzz_RevertIf_InvalidSignatureIsPassed( @@ -898,9 +907,11 @@ contract StakeOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, uint256 _currentNonce, - uint256 _randomSeed + uint256 _randomSeed, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); stdstore.target(address(uniStaker)).sig("nonces(address)").with_key(_depositor).checked_write( @@ -919,7 +930,8 @@ contract StakeOnBehalf is UniStakerTest { _delegatee, _beneficiary, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -942,7 +954,9 @@ contract StakeOnBehalf is UniStakerTest { vm.prank(_sender); vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); - uniStaker.stakeOnBehalf(_depositAmount, _delegatee, _beneficiary, _depositor, _signature); + uniStaker.stakeOnBehalf( + _depositAmount, _delegatee, _beneficiary, _depositor, _deadline, _signature + ); } } @@ -1307,9 +1321,11 @@ contract StakeMoreOnBehalf is UniStakerTest { uint256 _stakeMoreAmount, address _delegatee, address _beneficiary, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); @@ -1335,7 +1351,8 @@ contract StakeMoreOnBehalf is UniStakerTest { _depositId, _stakeMoreAmount, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -1344,7 +1361,7 @@ contract StakeMoreOnBehalf is UniStakerTest { bytes memory _signature = _sign(_depositorPrivateKey, _messageHash); vm.prank(_sender); - uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _depositor, _signature); + uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _depositor, _deadline, _signature); _deposit = _fetchDeposit(_depositId); @@ -1362,10 +1379,12 @@ contract StakeMoreOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, uint256 _currentNonce, - uint256 _suppliedNonce + uint256 _suppliedNonce, + uint256 _deadline ) public { vm.assume(_currentNonce != _suppliedNonce); vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _initialDepositAmount = _boundMintAmount(_initialDepositAmount); @@ -1387,7 +1406,12 @@ contract StakeMoreOnBehalf is UniStakerTest { bytes32 _message = keccak256( abi.encode( - uniStaker.STAKE_MORE_TYPEHASH(), _depositId, _stakeMoreAmount, _depositor, _suppliedNonce + uniStaker.STAKE_MORE_TYPEHASH(), + _depositId, + _stakeMoreAmount, + _depositor, + _suppliedNonce, + _deadline ) ); @@ -1397,7 +1421,7 @@ contract StakeMoreOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _depositor, _signature); + uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _depositor, _deadline, _signature); } function testFuzz_RevertIf_DepositorIsNotDepositOwner( @@ -1408,12 +1432,14 @@ contract StakeMoreOnBehalf is UniStakerTest { uint256 _stakeMoreAmount, address _delegatee, address _beneficiary, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _depositor != _notDepositor ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _initialDepositAmount = _boundMintAmount(_initialDepositAmount); _mintGovToken(_depositor, _initialDepositAmount); stdstore.target(address(uniStaker)).sig("nonces(address)").with_key(_depositor).checked_write( @@ -1430,7 +1456,7 @@ contract StakeMoreOnBehalf is UniStakerTest { ) ); vm.prank(_sender); - uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _notDepositor, ""); + uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _notDepositor, _deadline, ""); } function testFuzz_RevertIf_InvalidSignatureIsPassed( @@ -1441,9 +1467,11 @@ contract StakeMoreOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, uint256 _currentNonce, - uint256 _randomSeed + uint256 _randomSeed, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _initialDepositAmount = _boundMintAmount(_initialDepositAmount); @@ -1469,7 +1497,8 @@ contract StakeMoreOnBehalf is UniStakerTest { _depositId, _stakeMoreAmount, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -1488,7 +1517,7 @@ contract StakeMoreOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _depositor, _signature); + uniStaker.stakeMoreOnBehalf(_depositId, _stakeMoreAmount, _depositor, _deadline, _signature); } } @@ -1630,12 +1659,14 @@ contract AlterDelegateeOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, address _newDelegatee, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _newDelegatee != address(0) ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); @@ -1653,7 +1684,8 @@ contract AlterDelegateeOnBehalf is UniStakerTest { _depositId, _newDelegatee, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -1662,7 +1694,7 @@ contract AlterDelegateeOnBehalf is UniStakerTest { bytes memory _signature = _sign(_depositorPrivateKey, _messageHash); vm.prank(_sender); - uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _depositor, _signature); + uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _depositor, _deadline, _signature); _deposit = _fetchDeposit(_depositId); @@ -1677,13 +1709,15 @@ contract AlterDelegateeOnBehalf is UniStakerTest { address _beneficiary, address _newDelegatee, uint256 _currentNonce, - uint256 _suppliedNonce + uint256 _suppliedNonce, + uint256 _deadline ) public { vm.assume(_currentNonce != _suppliedNonce); vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _newDelegatee != address(0) ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _amount = _boundMintAmount(_amount); @@ -1697,7 +1731,12 @@ contract AlterDelegateeOnBehalf is UniStakerTest { bytes32 _message = keccak256( abi.encode( - uniStaker.ALTER_DELEGATEE_TYPEHASH(), _depositId, _newDelegatee, _depositor, _suppliedNonce + uniStaker.ALTER_DELEGATEE_TYPEHASH(), + _depositId, + _newDelegatee, + _depositor, + _suppliedNonce, + _deadline ) ); @@ -1707,7 +1746,7 @@ contract AlterDelegateeOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _depositor, _signature); + uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _depositor, _deadline, _signature); } function testFuzz_RevertIf_DepositorIsNotDepositOwner( @@ -1718,12 +1757,14 @@ contract AlterDelegateeOnBehalf is UniStakerTest { address _delegatee, address _newDelegatee, address _beneficiary, + uint256 _deadline, bytes memory _signature ) public { vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _depositor != _notDepositor ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _amount = _boundMintAmount(_amount); _mintGovToken(_depositor, _amount); @@ -1736,7 +1777,9 @@ contract AlterDelegateeOnBehalf is UniStakerTest { ) ); vm.prank(_sender); - uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _notDepositor, _signature); + uniStaker.alterDelegateeOnBehalf( + _depositId, _newDelegatee, _notDepositor, _deadline, _signature + ); } function testFuzz_RevertIf_InvalidSignatureIsPassed( @@ -1747,9 +1790,11 @@ contract AlterDelegateeOnBehalf is UniStakerTest { address _beneficiary, address _newDelegatee, uint256 _currentNonce, - uint256 _randomSeed + uint256 _randomSeed, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _amount = _boundMintAmount(_amount); @@ -1767,7 +1812,8 @@ contract AlterDelegateeOnBehalf is UniStakerTest { _depositId, _newDelegatee, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -1786,7 +1832,7 @@ contract AlterDelegateeOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _depositor, _signature); + uniStaker.alterDelegateeOnBehalf(_depositId, _newDelegatee, _depositor, _deadline, _signature); } } @@ -1924,12 +1970,14 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, address _newBeneficiary, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _newBeneficiary != address(0) ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); @@ -1947,7 +1995,8 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { _depositId, _newBeneficiary, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -1956,7 +2005,9 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { bytes memory _signature = _sign(_depositorPrivateKey, _messageHash); vm.prank(_sender); - uniStaker.alterBeneficiaryOnBehalf(_depositId, _newBeneficiary, _depositor, _signature); + uniStaker.alterBeneficiaryOnBehalf( + _depositId, _newBeneficiary, _depositor, _deadline, _signature + ); _deposit = _fetchDeposit(_depositId); @@ -1971,13 +2022,15 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { address _beneficiary, address _newBeneficiary, uint256 _currentNonce, - uint256 _suppliedNonce + uint256 _suppliedNonce, + uint256 _deadline ) public { vm.assume(_currentNonce != _suppliedNonce); vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _newBeneficiary != address(0) ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _amount = _boundMintAmount(_amount); @@ -1995,7 +2048,8 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { _depositId, _newBeneficiary, _depositor, - _suppliedNonce + _suppliedNonce, + _deadline ) ); @@ -2005,7 +2059,9 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.alterBeneficiaryOnBehalf(_depositId, _newBeneficiary, _depositor, _signature); + uniStaker.alterBeneficiaryOnBehalf( + _depositId, _newBeneficiary, _depositor, _deadline, _signature + ); } function testFuzz_RevertIf_DepositorIsNotDepositOwner( @@ -2016,12 +2072,14 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, address _newBeneficiary, + uint256 _deadline, bytes memory _signature ) public { vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _depositor != _notDepositor ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _amount = _boundMintAmount(_amount); _mintGovToken(_depositor, _amount); @@ -2034,7 +2092,9 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { ) ); vm.prank(_sender); - uniStaker.alterBeneficiaryOnBehalf(_depositId, _newBeneficiary, _notDepositor, _signature); + uniStaker.alterBeneficiaryOnBehalf( + _depositId, _newBeneficiary, _notDepositor, _deadline, _signature + ); } function testFuzz_RevertIf_InvalidSignatureIsPassed( @@ -2045,9 +2105,11 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { address _beneficiary, address _newBeneficiary, uint256 _currentNonce, - uint256 _randomSeed + uint256 _randomSeed, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _amount = _boundMintAmount(_amount); @@ -2065,7 +2127,8 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { _depositId, _newBeneficiary, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -2084,7 +2147,9 @@ contract AlterBeneficiaryOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.alterBeneficiaryOnBehalf(_depositId, _newBeneficiary, _depositor, _signature); + uniStaker.alterBeneficiaryOnBehalf( + _depositId, _newBeneficiary, _depositor, _deadline, _signature + ); } } @@ -2387,9 +2452,11 @@ contract WithdrawOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, uint256 _withdrawAmount, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); @@ -2409,7 +2476,8 @@ contract WithdrawOnBehalf is UniStakerTest { _depositId, _withdrawAmount, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -2418,7 +2486,7 @@ contract WithdrawOnBehalf is UniStakerTest { bytes memory _signature = _sign(_depositorPrivateKey, _messageHash); vm.prank(_sender); - uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _depositor, _signature); + uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _depositor, _deadline, _signature); _deposit = _fetchDeposit(_depositId); @@ -2433,10 +2501,12 @@ contract WithdrawOnBehalf is UniStakerTest { address _beneficiary, uint256 _withdrawAmount, uint256 _currentNonce, - uint256 _suppliedNonce + uint256 _suppliedNonce, + uint256 _deadline ) public { vm.assume(_currentNonce != _suppliedNonce); vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _depositAmount = _boundMintAmount(_depositAmount); @@ -2451,7 +2521,12 @@ contract WithdrawOnBehalf is UniStakerTest { bytes32 _message = keccak256( abi.encode( - uniStaker.WITHDRAW_TYPEHASH(), _depositId, _withdrawAmount, _depositor, _suppliedNonce + uniStaker.WITHDRAW_TYPEHASH(), + _depositId, + _withdrawAmount, + _depositor, + _suppliedNonce, + _deadline ) ); @@ -2461,7 +2536,7 @@ contract WithdrawOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _depositor, _signature); + uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _depositor, _deadline, _signature); } function testFuzz_RevertIf_DepositorIsNotDepositOwner( @@ -2472,12 +2547,14 @@ contract WithdrawOnBehalf is UniStakerTest { address _delegatee, address _beneficiary, uint256 _withdrawAmount, + uint256 _deadline, bytes memory _signature ) public { vm.assume( _delegatee != address(0) && _beneficiary != address(0) && _sender != address(0) && _depositor != _notDepositor ); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _amount = _boundMintAmount(_amount); _mintGovToken(_depositor, _amount); @@ -2490,7 +2567,7 @@ contract WithdrawOnBehalf is UniStakerTest { ) ); vm.prank(_sender); - uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _notDepositor, _signature); + uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _notDepositor, _deadline, _signature); } function testFuzz_RevertIf_InvalidSignatureIsPassed( @@ -2501,9 +2578,11 @@ contract WithdrawOnBehalf is UniStakerTest { address _beneficiary, uint256 _withdrawAmount, uint256 _currentNonce, - uint256 _randomSeed + uint256 _randomSeed, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _beneficiary != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _depositorPrivateKey = bound(_depositorPrivateKey, 1, 100e18); address _depositor = vm.addr(_depositorPrivateKey); _depositAmount = _boundMintAmount(_depositAmount); @@ -2522,7 +2601,8 @@ contract WithdrawOnBehalf is UniStakerTest { _depositId, _withdrawAmount, _depositor, - uniStaker.nonces(_depositor) + uniStaker.nonces(_depositor), + _deadline ) ); @@ -2541,7 +2621,7 @@ contract WithdrawOnBehalf is UniStakerTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _depositor, _signature); + uniStaker.withdrawOnBehalf(_depositId, _withdrawAmount, _depositor, _deadline, _signature); } } @@ -4532,7 +4612,8 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { uint256 _rewardAmount, address _delegatee, address _depositor, - uint256 _currentNonce + uint256 _currentNonce, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _depositor != address(0) && _sender != address(0)); _beneficiaryPrivateKey = bound(_beneficiaryPrivateKey, 1, 100e18); @@ -4549,6 +4630,7 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { _mintTransferAndNotifyReward(_rewardAmount); // A portion of the duration passes _jumpAheadByPercentOfRewardDuration(_durationPercent); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); uint256 _earned = uniStaker.unclaimedReward(_beneficiary); @@ -4557,7 +4639,9 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { ); bytes32 _message = keccak256( - abi.encode(uniStaker.CLAIM_REWARD_TYPEHASH(), _beneficiary, uniStaker.nonces(_beneficiary)) + abi.encode( + uniStaker.CLAIM_REWARD_TYPEHASH(), _beneficiary, uniStaker.nonces(_beneficiary), _deadline + ) ); bytes32 _messageHash = @@ -4565,7 +4649,7 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { bytes memory _signature = _sign(_beneficiaryPrivateKey, _messageHash); vm.prank(_sender); - uniStaker.claimRewardOnBehalf(_beneficiary, _signature); + uniStaker.claimRewardOnBehalf(_beneficiary, _deadline, _signature); assertEq(rewardToken.balanceOf(_beneficiary), _earned); } @@ -4579,7 +4663,8 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { address _delegatee, address _depositor, uint256 _currentNonce, - uint256 _suppliedNonce + uint256 _suppliedNonce, + uint256 _deadline ) public { vm.assume(_currentNonce != _suppliedNonce); vm.assume(_delegatee != address(0) && _depositor != address(0) && _sender != address(0)); @@ -4597,13 +4682,15 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { _mintTransferAndNotifyReward(_rewardAmount); // A portion of the duration passes _jumpAheadByPercentOfRewardDuration(_durationPercent); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); stdstore.target(address(uniStaker)).sig("nonces(address)").with_key(_beneficiary).checked_write( _currentNonce ); - bytes32 _message = - keccak256(abi.encode(uniStaker.CLAIM_REWARD_TYPEHASH(), _beneficiary, _suppliedNonce)); + bytes32 _message = keccak256( + abi.encode(uniStaker.CLAIM_REWARD_TYPEHASH(), _beneficiary, _suppliedNonce, _deadline) + ); bytes32 _messageHash = keccak256(abi.encodePacked("\x19\x01", EIP712_DOMAIN_SEPARATOR, _message)); @@ -4611,7 +4698,7 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.claimRewardOnBehalf(_beneficiary, _signature); + uniStaker.claimRewardOnBehalf(_beneficiary, _deadline, _signature); } function testFuzz_RevertIf_InvalidSignatureIsPassed( @@ -4621,9 +4708,11 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { address _depositor, address _delegatee, uint256 _currentNonce, - uint256 _randomSeed + uint256 _randomSeed, + uint256 _deadline ) public { vm.assume(_delegatee != address(0) && _depositor != address(0) && _sender != address(0)); + _deadline = bound(_deadline, block.timestamp + 1, type(uint256).max); _beneficiaryPrivateKey = bound(_beneficiaryPrivateKey, 1, 100e18); address _beneficiary = vm.addr(_beneficiaryPrivateKey); _depositAmount = _boundMintAmount(_depositAmount); @@ -4637,7 +4726,9 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { _boundMintAndStake(_depositor, _depositAmount, _delegatee, _beneficiary); bytes32 _message = keccak256( - abi.encode(uniStaker.CLAIM_REWARD_TYPEHASH(), _beneficiary, uniStaker.nonces(_beneficiary)) + abi.encode( + uniStaker.CLAIM_REWARD_TYPEHASH(), _beneficiary, uniStaker.nonces(_beneficiary), _deadline + ) ); bytes32 _messageHash = @@ -4655,7 +4746,7 @@ contract ClaimRewardOnBehalf is UniStakerRewardsTest { vm.expectRevert(UniStaker.UniStaker__InvalidSignature.selector); vm.prank(_sender); - uniStaker.claimRewardOnBehalf(_beneficiary, _signature); + uniStaker.claimRewardOnBehalf(_beneficiary, _deadline, _signature); } }