Sparkn

CodeFox Inc.
DeFiFoundryProxy
15,000 USDC
View results
Submission Details
Severity: low
Valid

Potential underpayment and trapped funds due to Decimals

Summary

Using the sample whitelisted tokens listed in ProxyFactory.sol's constructor function's Natspec comments as a guide (see link), there is a potential variation in decimal precision.
Across whitelisted tokens, the _distribute function may result in precision loss during prize distribution. Tokens with lower decimal precision (e.g., 6 decimals) may lead to winners receiving fewer funds or, not receiving any funds at all. This will require manual intervention to fix.

Vulnerability Details

Consider a contest where the token is USDT (6 decimals) and the prize fund is less 0.01 USDT (1e4).
For the winner distribution data, the Organizer allocates 1 basis point, the minimum allowable percentage (0.01%), in the percentages array to a winner.

Given the 6 decimal precision of USDT, BASIS_POINTS = 10000 and the prize fund is less than 0.01 USDT, the amount of USDT corresponding to 1 basis point will be less than the token's smallest divisible unit (which is 0.000001).

Given Solidity's arithmetic, the line uint256 amount = (totalAmount * percentages[i]) / BASIS_POINTS (linked) will truncate to 0. Therefore when the line erc20.safeTransfer(winners[i], amount) makes a call to the USDT ERC20 contract with a value of 0, the call will be reverted.

The loop will be broken and those winners before the break will recieve their prizes but the winner in scenario and those coming afterwards in the loop will not.

Whitelised Tokens (from Natspec comments)

  • DAI -> ETH 18 dec

  • JPYC -> ETH 18 dec

  • USDT -> ETH 6 dec

  • USDC -> ETH 6 dec

Impact

  1. Wasted gas and computation - inefficient executions may deter users from interacting with the protocol.

  2. Users in the loop before the loop is broken as in the example above will recieve funds.

  3. Deployment of the proxy contract without resolution of contest which is the intended purpose of the protocol.

  4. Manual intervention required to rectify; i.e. triggering of distributeByOwner in proxyFactory.sol to pay the winners which could only be done after the EXPIRATION_TIME (7 days) which would lead a bad user experience and unnecessary admin overhead for the protocol runners

Tools Used

Manual Code Review
Foundry
Remix

Recommendations

A simple fix would be to update L142; raising the minimum value required to fund a contest from 0 to 10000 (1e4).

if (totalAmount == 0) revert Distributor__NoTokenToDistribute();

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!