PoolTogether TWAB Delegator contest - Omik's results

A protocol for no loss prize savings on Ethereum

General Information

Platform: Code4rena

Start Date: 22/02/2022

Pot Size: $30,000 USDC

Total HM: 1

Participants: 22

Period: 3 days

Judge: leastwood

Id: 93

League: ETH

PoolTogether

Findings Distribution

Researcher Performance

Rank: 1/22

Findings: 2

Award: $7,687.95

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: kirk-baird

Also found by: Omik, cmichel

Labels

bug
duplicate
2 (Med Risk)

Awards

7650 USDC - $7,650.00

External Links

LOW : 1. Title : permitAndMulticall() can be frontrun, that will lead to the user must reasign the TX

Impact : In the permitAndMulticall() it takes from as a user input, since all tx in the blockchain is public, a malicious user might frontrun the permitAndMulticall() and providing 0 data, which will increment the nonce of the from user in the erc20permit, by the time the original from user tx get executed it will be revert since the nonce already inflate, and the original user must re-sign.

POC : https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/TWABDelegator.sol#L444

Mitigation : remove the from parameter, and change the from to msg.sender.

Title : Code didnt match with the documentation for representative flow

Impact : In the https://dev.pooltogether.com/protocol/contracts/v4-twab-delegator/ it explain that the the delegator must stake first before the representative can createDelegation, but in the https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/TWABDelegator.sol#L400 the delegator can set a representative and the code didnt check if the delegator already have stake a token or not, after setting a representative the representative than allow to call createDelegation with the delegator stake a token first.

POC : https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/TWABDelegator.sol#L400

#0 - PierrickGT

2022-03-02T17:59:35Z

Title : permitAndMulticall() can be frontrun, that will lead to the user must reasign the TX

Duplicate of https://github.com/code-423n4/2022-02-pooltogether-findings/issues/20

Title : Code didnt match with the documentation for representative flow

This is an example flow, the order of operations can differ and the code don't have to match with it. It is indeed possible to set a representative before staking but without any staked amount, a representative will only be able to create a delegation and not fund it.

#1 - 0xleastwood

2022-03-13T05:38:01Z

I think it is fair to have this upgraded to medium severity considering the fact that the warden has outlined the potential issue. While it is mostly up to wardens to effectively identify the correct severity for an issue, I think in this instance, the warden has provided a clear attack vector. As such, I'll ignore this for QA report consideration and just bump it to medium.

Findings Information

🌟 Selected for report: CertoraInc

Also found by: 0x1f8b, Dravee, IllIllI, Omik, Tomio, WatchPug, gzeon, hickuphh3, kenta, nascent, pedroais, rfa, robee, sorrynotsorry, ye0lde, z3s

Awards

37.9471 USDC - $37.95

Labels

bug
G (Gas Optimization)

External Links

GAS : 1. Title : using uint96 in a struct can save gas

Impact : By changing the call struct inside delegation contract from using uint256 to uint96 can save some gas, because the current struct is using 3 slot storage, by changing it to uint96, the address and uint96 will be placed in the same slot, therefore it only take 2 slot spaces.

POC : https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/Delegation.sol#L15

Title : unnecesary check on _requireDelegatorOrRepresentative()

Impact : There is no need to check if the representatives[_delegator][msg.sender] == true, because if the delegator already set the msg.sender as the representative the value would be true, by removing == true will save some gas

POC : https://github.com/pooltogether/v4-twab-delegator/blob/2b6d42506187dd7096043e2dfec65fa06ab18577/contracts/TWABDelegator.sol#L583

Mitigation :

function _requireDelegatorOrRepresentative(address _delegator) internal view { require( _delegator == msg.sender || representatives[_delegator][msg.sender], "TWABDelegator/not-delegator-or-rep" ); }

#0 - PierrickGT

2022-03-02T00:43:47Z

using uint96 in a struct can save gas

It actually becomes more gas expensive to store a uint96 instead of a uint256 and this because value will need to be downcasted from uint256 to uint96 when calling executeCall. I did some gas golfing with the createDelegation function and the results are the following.

With uint256 (on average): 135,687 With uint96 (on average): 135,745

unnecesary check on _requireDelegatorOrRepresentative()

Duplicate of https://github.com/code-423n4/2022-02-pooltogether-findings/issues/15

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter