Skip to content

Commit

Permalink
make future withdrawals unimpacted by previous cancellations (#1194)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbrent committed Sep 10, 2024
1 parent 8697de8 commit f90e0e0
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
3 changes: 1 addition & 2 deletions contracts/p0/StRSR.sol
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@ contract StRSRP0 is IStRSR, ComponentP0, EIP712Upgradeable {
uint256 i = start;
for (; i < endId; i++) {
total += queue[i].rsrAmount;
queue[i].rsrAmount = 0;
queue[i].stakeAmount = 0;
delete queue[i];
}

// Execute accumulated withdrawals
Expand Down
4 changes: 3 additions & 1 deletion contracts/p1/StRSR.sol
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,9 @@ abstract contract StRSRP1 is Initializable, ComponentP1, IStRSR, EIP712Upgradeab
index = queue.length;

uint192 oldDrafts = index != 0 ? queue[index - 1].drafts : 0;
uint64 lastAvailableAt = index != 0 ? queue[index - 1].availableAt : 0;
uint64 lastAvailableAt = index != 0 && firstRemainingDraft[draftEra][account] < index
? queue[index - 1].availableAt
: 0;
availableAt = uint64(block.timestamp) + unstakingDelay;
if (lastAvailableAt > availableAt) {
availableAt = lastAvailableAt;
Expand Down
43 changes: 43 additions & 0 deletions test/ZZStRSR.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,49 @@ describe(`StRSRP${IMPLEMENTATION} contract`, () => {
.withArgs(0, 2, addr1.address, amount.div(2), amount, anyValue)
})

it('Should not impact future withdrawals after cancellation -- regression test 9/04/2024', async () => {
// Context: https://github.com/code-423n4/2024-07-reserve-findings/issues/18

// old unstakingDelay is 1 day
const oldUnstakingDelay = 3600 * 24
await stRSR.connect(owner).setUnstakingDelay(oldUnstakingDelay)
const amount: BigNumber = bn('100e18')
await rsr.connect(addr1).approve(stRSR.address, amount)
await stRSR.connect(addr1).stake(amount)

const draftEra = 1
const availableAtOfFirst = (await getLatestBlockTimestamp()) + oldUnstakingDelay + 1
/**
* Unstaking request enter a queue, and withdrawal become available 1 day later
*/
await expect(stRSR.connect(addr1).unstake(amount))
.emit(stRSR, 'UnstakingStarted')
.withArgs(0, draftEra, addr1.address, amount, amount, availableAtOfFirst)

/**
* Cancel the unstaking to eliminate any pending withdrawals
*/
await stRSR.connect(addr1).cancelUnstake(1)

// new unstakingDelay is 1 hour
const newUnstakingDelay = 3600
await stRSR.connect(owner).setUnstakingDelay(newUnstakingDelay)

await rsr.connect(addr2).approve(stRSR.address, amount)
await stRSR.connect(addr2).stake(amount)

const availableAtOfFirstOfUser2 = (await getLatestBlockTimestamp()) + newUnstakingDelay + 1
/**
* Unstaking request enter a queue. Withdrawal should become available 1 hour later for both users
*/
await expect(stRSR.connect(addr2).unstake(amount))
.emit(stRSR, 'UnstakingStarted')
.withArgs(0, draftEra, addr2.address, amount, amount, availableAtOfFirstOfUser2)
await expect(stRSR.connect(addr1).unstake(amount))
.emit(stRSR, 'UnstakingStarted')
.withArgs(1, draftEra, addr1.address, amount, amount, availableAtOfFirstOfUser2 + 1)
})

it('Should create Pending withdrawal when unstaking', async () => {
const amount: BigNumber = bn('1000e18')

Expand Down

0 comments on commit f90e0e0

Please sign in to comment.