Lucene search

K
code423n4Code4renaCODE423N4:2021-12-POOLTOGETHER-FINDINGS-ISSUES-61
HistoryDec 12, 2021 - 12:00 a.m.

Malicious Promotion Creators Can Drain Token Balances

2021-12-1200:00:00
Code4rena
github.com
7

Handle

leastwood

Vulnerability details

Impact

The createPromotion allows any user to create and fund promotions for a specific number of epochs. Ticket holders are entitled to a percentage of the rewards based on their TWAB. createPromotion references a _ticket address which can be controlled by the creator account. The requireTicket function is meant to validate the _ticket address, however, this can be bypassed by setting _ticket to a user controlled contract which returns valid values. Consequently, the malicious user can alter the result returned from _calculateRewardAmount and effectively drain the balance of ANY target token.

The affected function, claimRewards, does not check that the _rewardsAmount sent to a user is <= to to total rewards declared when creating a promotion. As a result, there is a risk that users can lose funds, hence this issue should be of high severity.

Proof of Concept

The POC consists of a series of steps an attacker must follow in order to exploit this contract and drain it of its token balance.

  • The attacker creates a contract which satisfies the _requireTicket function. This contract must simply return a non-zero controllerAddress when a staticcall is made on the controller.selector.

  • Valid input values to the createPromotion function are provided, including a non-zero amount _tokensPerEpoch and target token _token. The function will transfer some small non-zero amount from the attacker.

  • One epoch passes and the creator of the promotion (who is also a ticket holder), calls claimRewards on the epochId which has just passed.

  • The claimRewards function iterates through the single epochId and makes an internal call to _calculateRewardAmount

  • The attacker controls the _ticket contract, which allows them to control the return values for the two functions _ticket.getAverageTotalSuppliesBetween and _ticket.getAverageBalanceBetween in _calculateRewardAmount. The following calculation dictates the returned reward amount.

    return (_promotion.tokensPerEpoch * _averageBalance) / _averageTotalSupplies[0];

  • As there is no inherent check to ensure that _rewardsAmount is <= to the number of tokens provided to the user’s promotion, the attacker can control this value and set it to an amount larger than their provided token amount. Therefore, the attacker can effectively withdraw ANY amount of tokens from the TwabRewards contract, belonging to target token _token.

  • This can be repeated with multiple promotions utilising various _token arguments to drain the contract balance for ALL tokens.

Tools Used

Manual code review.

Recommended Mitigation Steps

Consider whitelisting _ticket contracts within TwabRewards. Alternatively, a more succinct solution could be to track the total rewards claimed for a given promotion. This should prevent more tokens from being sent out than provider by the promotion’s creator.


The text was updated successfully, but these errors were encountered:

All reactions