From 45a79e5c63f3bf8f6aa7f4f0a48494cdb3d62607 Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Tue, 28 Jan 2025 22:53:49 +0200 Subject: [PATCH 1/7] fix: added minimum check to rebalance in case of residual being low --- contracts/governance/locking/LockingRelock.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/governance/locking/LockingRelock.sol b/contracts/governance/locking/LockingRelock.sol index f8fdaa3..f6a2fef 100644 --- a/contracts/governance/locking/LockingRelock.sol +++ b/contracts/governance/locking/LockingRelock.sol @@ -117,6 +117,7 @@ abstract contract LockingRelock is LockingBase { */ function rebalance(uint256 id, address account, uint96 bias, uint96 residue, uint96 newAmount) internal { require(residue <= newAmount, "Impossible to relock: less amount, then now is"); + require(newAmount >= 1e18, "amount is less than minimum"); uint96 addAmount = newAmount - (residue); uint96 amount = accounts[account].amount; uint96 balance = amount - (bias); From 1d7c45199b64974b919e9e82681629119aaee563 Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Wed, 29 Jan 2025 19:50:21 +0200 Subject: [PATCH 2/7] chore: added unit test --- test/unit/governance/Locking/relock.t.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/unit/governance/Locking/relock.t.sol b/test/unit/governance/Locking/relock.t.sol index 1676a3e..cd6a13c 100644 --- a/test/unit/governance/Locking/relock.t.sol +++ b/test/unit/governance/Locking/relock.t.sol @@ -646,4 +646,19 @@ contract Relock_LockingTest is LockingTest { assertEq(mentoToken.balanceOf(bob), 100e18); assertEq(mentoToken.balanceOf(charlie), 100e18); } + + function test_relock_whenAmountLessThanMinimum_shouldRevert() public { + mentoToken.mint(alice, 100e18); + + vm.prank(alice); + lockId = locking.lock(alice, alice, 30e18, 3, 3); + + // Wait until lock expires so residue is 0 + _incrementBlock(6 * weekInBlocks); + + // Try to relock with amount less than minimum (1e18) + vm.expectRevert("amount is less than minimum"); + vm.prank(alice); + locking.relock(lockId, alice, 0.5e18, 3, 3); + } } From 5fdf004ba3372ecacb3ca6cc2733d7af0df52fde Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Wed, 29 Jan 2025 19:57:40 +0200 Subject: [PATCH 3/7] chore: added success test --- test/unit/governance/Locking/relock.t.sol | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/unit/governance/Locking/relock.t.sol b/test/unit/governance/Locking/relock.t.sol index cd6a13c..1e64520 100644 --- a/test/unit/governance/Locking/relock.t.sol +++ b/test/unit/governance/Locking/relock.t.sol @@ -661,4 +661,18 @@ contract Relock_LockingTest is LockingTest { vm.prank(alice); locking.relock(lockId, alice, 0.5e18, 3, 3); } + + function test_relock_whenAmountIsMinimum_shouldRelockSuccessfully() public { + mentoToken.mint(alice, 100e18); + + vm.prank(alice); + lockId = locking.lock(alice, alice, 30e18, 3, 3); + + // Wait until lock expires so residue is 0 + _incrementBlock(6 * weekInBlocks); + + // Should succeed with amount = minimum + vm.prank(alice); + locking.relock(lockId, alice, 1e18, 3, 3); + } } From 02f443e48f3bf8c5c464c724e45164468aed58e1 Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Mon, 3 Feb 2025 18:48:02 +0200 Subject: [PATCH 4/7] fix: moved check to verification --- contracts/governance/locking/LockingRelock.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/governance/locking/LockingRelock.sol b/contracts/governance/locking/LockingRelock.sol index f6a2fef..1d934dc 100644 --- a/contracts/governance/locking/LockingRelock.sol +++ b/contracts/governance/locking/LockingRelock.sol @@ -68,6 +68,7 @@ abstract contract LockingRelock is LockingBase { uint32 toTime ) internal view { require(newAmount > 0, "zero amount"); + require(newAmount >= 1e18, "amount is less than minimum"); require(newCliff <= MAX_CLIFF_PERIOD, "cliff too big"); require(newSlopePeriod <= MAX_SLOPE_PERIOD, "slope period too big"); require(newSlopePeriod > 0, "slope period equal 0"); @@ -117,7 +118,6 @@ abstract contract LockingRelock is LockingBase { */ function rebalance(uint256 id, address account, uint96 bias, uint96 residue, uint96 newAmount) internal { require(residue <= newAmount, "Impossible to relock: less amount, then now is"); - require(newAmount >= 1e18, "amount is less than minimum"); uint96 addAmount = newAmount - (residue); uint96 amount = accounts[account].amount; uint96 balance = amount - (bias); From 784ef132ebd9873c64cae8ae35f56831c06c01bb Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Wed, 5 Feb 2025 11:13:59 +0200 Subject: [PATCH 5/7] fix: redundant check --- contracts/governance/locking/LockingRelock.sol | 1 - test/unit/governance/Locking/relock.t.sol | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/governance/locking/LockingRelock.sol b/contracts/governance/locking/LockingRelock.sol index 1d934dc..f01104d 100644 --- a/contracts/governance/locking/LockingRelock.sol +++ b/contracts/governance/locking/LockingRelock.sol @@ -67,7 +67,6 @@ abstract contract LockingRelock is LockingBase { uint32 newCliff, uint32 toTime ) internal view { - require(newAmount > 0, "zero amount"); require(newAmount >= 1e18, "amount is less than minimum"); require(newCliff <= MAX_CLIFF_PERIOD, "cliff too big"); require(newSlopePeriod <= MAX_SLOPE_PERIOD, "slope period too big"); diff --git a/test/unit/governance/Locking/relock.t.sol b/test/unit/governance/Locking/relock.t.sol index 1e64520..20b9c6e 100644 --- a/test/unit/governance/Locking/relock.t.sol +++ b/test/unit/governance/Locking/relock.t.sol @@ -230,7 +230,7 @@ contract Relock_LockingTest is LockingTest { lockId = locking.lock(alice, alice, 38e18, 4, 3); _incrementBlock(2 * weekInBlocks); - vm.expectRevert("zero amount"); + vm.expectRevert("amount is less than minimum"); vm.prank(alice); locking.relock(lockId, alice, 0, 5, 1); } From 3bdd02e54b8fff4ac8ed184636b2387b5477938f Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Wed, 5 Feb 2025 13:55:39 +0200 Subject: [PATCH 6/7] chore: remove comments --- test/unit/governance/Locking/relock.t.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/unit/governance/Locking/relock.t.sol b/test/unit/governance/Locking/relock.t.sol index 20b9c6e..589be57 100644 --- a/test/unit/governance/Locking/relock.t.sol +++ b/test/unit/governance/Locking/relock.t.sol @@ -653,10 +653,8 @@ contract Relock_LockingTest is LockingTest { vm.prank(alice); lockId = locking.lock(alice, alice, 30e18, 3, 3); - // Wait until lock expires so residue is 0 _incrementBlock(6 * weekInBlocks); - // Try to relock with amount less than minimum (1e18) vm.expectRevert("amount is less than minimum"); vm.prank(alice); locking.relock(lockId, alice, 0.5e18, 3, 3); @@ -668,10 +666,8 @@ contract Relock_LockingTest is LockingTest { vm.prank(alice); lockId = locking.lock(alice, alice, 30e18, 3, 3); - // Wait until lock expires so residue is 0 _incrementBlock(6 * weekInBlocks); - // Should succeed with amount = minimum vm.prank(alice); locking.relock(lockId, alice, 1e18, 3, 3); } From b83f08e89d0838ce3ba927c704a38d0d48747b28 Mon Sep 17 00:00:00 2001 From: Ryan Noble Date: Wed, 5 Feb 2025 14:06:05 +0200 Subject: [PATCH 7/7] chore: semantics --- contracts/governance/locking/LockingRelock.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/governance/locking/LockingRelock.sol b/contracts/governance/locking/LockingRelock.sol index f01104d..66e2e6f 100644 --- a/contracts/governance/locking/LockingRelock.sol +++ b/contracts/governance/locking/LockingRelock.sol @@ -26,6 +26,7 @@ abstract contract LockingRelock is LockingBase { uint32 newSlopePeriod, uint32 newCliff ) external returns (uint256) { + require(newAmount >= 1e18, "amount is less than minimum"); require(newDelegate != address(0), "delegate is zero"); address account = verifyLockOwner(id); @@ -67,7 +68,6 @@ abstract contract LockingRelock is LockingBase { uint32 newCliff, uint32 toTime ) internal view { - require(newAmount >= 1e18, "amount is less than minimum"); require(newCliff <= MAX_CLIFF_PERIOD, "cliff too big"); require(newSlopePeriod <= MAX_SLOPE_PERIOD, "slope period too big"); require(newSlopePeriod > 0, "slope period equal 0");