Lucene search

K
code423n4Code4renaCODE423N4:2022-02-POOLTOGETHER-FINDINGS-ISSUES-21
HistoryFeb 24, 2022 - 12:00 a.m.

TWABDelegator allows easy circumvention of whale protection

2022-02-2400:00:00
Code4rena
github.com
3
pooltogether
twabdelegator
whale protection
liquidity aggregation
delegation
vulnerability

Lines of code

Vulnerability details

In a recent interview, PoolTogether co-founder Leighton Cusack said:

“Someone who had $1,000 right now into the USDC prize pool would have a 0.01% chance of winning a prize every week. That’s a less than 1% chance of winning a prize a year,” Cusack said. “With the new PoolTogether, someone with $1,000 deposited will have a 10% chance of winning a prize each week.”

<https://www.coindesk.com/business/2021/10/15/pooltogether-launches-v4-more-prizes-better-odds-and-aggregated-liquidity/&gt;

The article later goes on to say that the important changes in v4 are whale protection and liquidity aggregation. Both of these features make the ability to circumvent whale controls more valuable.

Impact

Whale protection is essentially the fact that each account may only claim a limited number of picks. In order to be able to delegate tickets to multiple different accounts, the approach the TWABDelegator took was to transfer tickets to new accounts that the user is not able to directly control, but can retrieve when the backing funds are required. This is essentially a workaround for the whale protection (splitting one account into multiple smaller accounts). By doing this as efficiently as possible, this feature gives whales a simple way to structure their funds to circumvent the protections. Now that the v4 pools share liquidity, the whales get a much larger reward for taking advantage of this ability. Without adequate and active monitoring, loss of confidence in PoolTogether due to this new ability will impact the longevity of this version of PoolTogether and thus the longevity of this feature. I’ve marked this as ‘High’ because the feature allows whales to win prizes that are designed to go to other users.

Proof of Concept

TWABDelegator.createDelegation() creates a new address for every creation:

  function _createDelegation(bytes32 _salt, uint96 _lockUntil) internal returns (Delegation) {
    Delegation _delegation = Delegation(address(delegationInstance).cloneDeterministic(_salt));
    _delegation.initialize(_lockUntil);
    return _delegation;
  }

<https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/LowLevelDelegator.sol#L28-L32&gt;

And delegation is transfering the tickets to the new address:

    IERC20(ticket).safeTransferFrom(msg.sender, address(_delegation), _amount);

<https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/TWABDelegator.sol#L304&gt;

Tools Used

Code inspection

Recommended Mitigation Steps

Track all source addresses of delegations using TWABDelegator from within the TWABDelegator and let users easily look up the largest users of the feature using functions added to the contract. Also rate limit the creation of delegations, limit the size of multicalls, and release regular reports about use of the feature.


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

All reactions