From 7bb56cdb4eec5ceff862eaa6c032af4cd91b5293 Mon Sep 17 00:00:00 2001 From: Edwin O Date: Fri, 4 Mar 2022 14:28:13 +0100 Subject: [PATCH] Get pending withdrawal (#9369) ### Description LockedGold.sol currently provides a way to retrieve all pendingWithdrawals associated to a given account. To be able to extract a pendingWithdrawal at specific index, one would need to first do getPendingWithdrawals and then loop through the result to find the record 0(n) and has a DOS vector as found by @tkporter ### Tested - [x] unit test ### Related issues https://app.zenhub.com/workspaces/yield-61b75a715d3ecb001007ab9d/issues/celo-org/yield/16 ### Backwards compatibility _Brief explanation of why these changes are/are not backwards compatible._ This change is backward compatible because it is completely transparent and does not modify existing function signatures etc --- .../contracts/governance/LockedGold.sol | 21 ++++++++++++++++++- .../test/governance/voting/lockedgold.ts | 9 ++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/protocol/contracts/governance/LockedGold.sol b/packages/protocol/contracts/governance/LockedGold.sol index 32ebb93e43a..3a798d8b9c1 100644 --- a/packages/protocol/contracts/governance/LockedGold.sol +++ b/packages/protocol/contracts/governance/LockedGold.sol @@ -81,7 +81,7 @@ contract LockedGold is * @return The storage, major, minor, and patch version of the contract. */ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { - return (1, 1, 1, 2); + return (1, 1, 2, 0); } /** @@ -284,6 +284,25 @@ contract LockedGold is return (values, timestamps); } + /** + * @notice Returns the pending withdrawal at a given index for a given account. + * @param account The address of the account. + * @param index The index of the pending withdrawal. + * @return The value of the pending withdrawal. + * @return The timestamp of the pending withdrawal. + */ + function getPendingWithdrawal(address account, uint256 index) + external + view + returns (uint256, uint256) + { + require(getAccounts().isAccount(account), "Unknown account"); + require(index < balances[account].pendingWithdrawals.length, "Bad pending withdrawal index"); + PendingWithdrawal memory pendingWithdrawal = (balances[account].pendingWithdrawals[index]); + + return (pendingWithdrawal.value, pendingWithdrawal.timestamp); + } + /** * @notice Returns the total amount to withdraw from unlocked gold for an account. * @param account The address of the account. diff --git a/packages/protocol/test/governance/voting/lockedgold.ts b/packages/protocol/test/governance/voting/lockedgold.ts index c10a39e64eb..fa0431bf171 100644 --- a/packages/protocol/test/governance/voting/lockedgold.ts +++ b/packages/protocol/test/governance/voting/lockedgold.ts @@ -203,11 +203,10 @@ contract('LockedGold', (accounts: string[]) => { }) it('should add a pending withdrawal', async () => { - const [values, timestamps] = await lockedGold.getPendingWithdrawals(account) - assert.equal(values.length, 1) - assert.equal(timestamps.length, 1) - assertEqualBN(values[0], value) - assertEqualBN(timestamps[0], availabilityTime) + const [val, timestamp] = await lockedGold.getPendingWithdrawal(account, 0) + assertEqualBN(val, value) + assertEqualBN(timestamp, availabilityTime) + await assertRevert(lockedGold.getPendingWithdrawal(account, 1)) }) it("should decrease the account's nonvoting locked gold balance", async () => {