Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two address tokens can be withdrawn by the admin even if they are vested #429

Open
code423n4 opened this issue Sep 23, 2022 · 2 comments
Open
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2022-09-vtvl/blob/f68b7f3e61dad0d873b5b5a1e8126b839afeab5f/contracts/VTVLVesting.sol#L446-L451

Vulnerability details

Impact

Two address tokens exists in the blockchain. For example, Synthetix's ProxyERC20 contract is such a token which exists in many forms (sUSD, sBTC...). Tokens as such can be vested, but the admin can withdraw them even if they are vested by providing the other address to the withdrawOtherToken function. The only check in this function is that _otherTokenAddress != tokenAddress, which is irrelevant in the case of two address tokens.

This can make the admin be able to withdraw the vested funds and break the system, because the balance of the contract can be less than the vested amount.

Proof of Concept

  1. The VTVLVesting is deployed with the sUSD contract, using its main (proxy) address - 0x57Ab1ec28D129707052df4dF418D58a2D46d5f51.
  2. A claim is created for Alice, vesting 1000 sUSD in linear vesting. Assuming this is the only claim currently, the balance of the contract is 1000 sUSD and the value of numTokensReservedForVesting is 1000e18.
  3. The admin calls the withdrawOtherToken for 1000e18 sUSD, providing its second address - 0x57Ab1ec28D129707052df4dF418D58a2D46d5f51. The value of numTokensReservedForVesting is still 1000e18, but the balance of the contract is now 0 sUSD.
  4. Alice waits for her vest to end, calls the withdraw function, but the function reverts on the call to safeTransfer() because there is insufficient balance of sUSD. Alice can't receive her funds.

Tools Used

Manual audit

Recommended Mitigation Steps

Replace the address check with a balance check - record the vesting token balance of the contract before and after the transfer and assert that they are equal.

@code423n4 code423n4 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Sep 23, 2022
code423n4 added a commit that referenced this issue Sep 23, 2022
@0xean
Copy link
Collaborator

0xean commented Sep 24, 2022

downgrading to M. The fix is a good idea, but this is a pretty rare token implementation and definitely qualifies as an external factor.

@0xean 0xean added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value and removed 3 (High Risk) Assets can be stolen/lost/compromised directly labels Sep 24, 2022
@lawrencehui lawrencehui added the sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons label Oct 7, 2022
@lawrencehui
Copy link
Collaborator

yes agreed with @0xean that this is very rare and appreciate warden's suggestion on the fix on balance checking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons
Projects
None yet
Development

No branches or pull requests

3 participants