Streaming Protocol contest - pauliax's results

General Information

Platform: Code4rena

Start Date: 30/11/2021

Pot Size: $100,000 USDC

Total HM: 15

Participants: 36

Period: 7 days

Judge: 0xean

Total Solo HM: 4

Id: 62

League: ETH

Streaming Protocol

Findings Distribution

Researcher Performance

Rank: 15/36

Findings: 4

Award: $2,487.20

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: cmichel

Also found by: 0x0x0x, Ruhum, gpersoon, gzeon, hack3r-0m, pauliax

Labels

bug
duplicate
3 (High Risk)

Awards

611.7761 USDC - $611.78

External Links

Handle

pauliax

Vulnerability details

Impact

function createStream should validate that depositToken != rewardToken, otherwise, some functionality may not work as intended, e.g. in function recoverTokens it will become impossible to reach the second 'if' statement.

require depositToken != rewardToken

#0 - 0xean

2022-01-14T21:04:47Z

dupe of #215

Findings Information

🌟 Selected for report: harleythedog

Also found by: hyh, kenzo, pauliax, pedroais

Labels

bug
duplicate
3 (High Risk)

Awards

1057.3907 USDC - $1,057.39

External Links

Handle

pauliax

Vulnerability details

Impact

function creatorClaimSoldTokens should nullify depositTokenAmount, otherwise it may not be possible to recover deposit tokens later because the balance will be lower than accounted depositTokenAmount:

  uint256 excess = ERC20(token).balanceOf(address(this)) - (depositTokenAmount - redeemedDepositTokens);

Possible solution (function creatorClaimSoldTokens):

    uint112 amount = depositTokenAmount;
    depositTokenAmount = 0;

#0 - 0xean

2022-01-15T01:31:47Z

dupe of #121

Findings Information

🌟 Selected for report: Omik

Also found by: pauliax

Labels

bug
duplicate
1 (Low Risk)
sponsor disputed

Awards

362.6168 USDC - $362.62

External Links

Handle

pauliax

Vulnerability details

Impact

functions transfer and transferFrom could validate that 'to' is not an empty address to prevent accidental burns. recoverTokens could validate that recipient is not empty. Function creatorClaimSoldTokens and claimFees could prevent an empty destination. Similarly, acceptGov could check that pendingGov is not a zero address.

Consider validating that mentioned address parameters are not empty.

#0 - brockelmore

2022-01-05T17:38:38Z

duplicate #136

Findings Information

🌟 Selected for report: Meta0xNull

Also found by: pauliax, robee

Labels

bug
duplicate
1 (Low Risk)

Awards

217.5701 USDC - $217.57

External Links

Handle

pauliax

Vulnerability details

Impact

There are TODOs left in the code. While this does not cause any direct issue, it indicates a bad smell and uncertainty:

  // TODO: we could have start_time+stream_duration+depositlocktime as maturity-date
  // TODO: figure out sane salt, i.e. streamid + x? streamid guaranteed to be unique

Consider either fixing TODOs or removing them to avoid confusion.

#0 - 0xean

2022-01-16T14:12:42Z

dupe of #78

Findings Information

🌟 Selected for report: gpersoon

Also found by: GiveMeTestEther, Meta0xNull, bitbopper, hack3r-0m, pauliax, pedroais, wuwe1

Labels

bug
duplicate
1 (Low Risk)
disagree with severity

Awards

48.1774 USDC - $48.18

External Links

Handle

pauliax

Vulnerability details

Impact

function updateStreamInternal accepts a parameter 'who' but uses msg.sender when accessing the stream:

  function updateStreamInternal(address who) internal {
    ...
    TokenStream storage ts = tokensNotYetStreamed[msg.sender];

This will not update the expected stream when who != msg.sender. Currently, this function is only called from within the modifier, and the modifier is applied with msg.sender only, but still this risk needs to be addressed.

Consider either updating 'who', or totally getting rid of this parameter to avoid confusion.

#0 - brockelmore

2022-01-05T17:37:19Z

gas optimization

#1 - brockelmore

2022-01-05T17:37:31Z

duplicate #125

Findings Information

🌟 Selected for report: 0x0x0x

Also found by: WatchPug, kenzo, pauliax

Labels

bug
duplicate
G (Gas Optimization)

Awards

18.2633 USDC - $18.26

External Links

Handle

pauliax

Vulnerability details

Impact

function exit performs updateStream and then calls withdraw but withdraw also has a updateStream modifier so this update is executed twice. Because you probably need an exit to have an up to date ts.tokens, an option to consider is extracting an internal _withdraw function with no updateStream modifier and you can re-use it with both exit and withdraw.

#0 - 0xean

2022-01-17T13:50:22Z

dupe of #187

Findings Information

🌟 Selected for report: 0x0x0x

Also found by: 0x1f8b, GeekyLumberjack, WatchPug, cmichel, danb, pauliax

Labels

bug
duplicate
G (Gas Optimization)

Awards

7.608 USDC - $7.61

External Links

Handle

pauliax

Vulnerability details

Impact

This can be simplified to avoid useless calculations:

  uint112 feeAmt = amount * 10 / 10000; // 10bps fee
  uint112 feeAmt = amount / 1000; // 0.1% fee

#0 - 0xean

2022-01-17T13:56:17Z

dupe of #188

Findings Information

🌟 Selected for report: Omik

Also found by: gzeon, pauliax

Labels

bug
duplicate
G (Gas Optimization)

Awards

27.0568 USDC - $27.06

External Links

Handle

pauliax

Vulnerability details

Impact

Don't need an empty else clause here:

  if (!isSale) {
      _burn(msg.sender, amount);
  } else {
  }
  
  if (!isSale) {
    // not a straight sale, so give the user some receipt tokens
    _mint(msg.sender, trueDepositAmt);
  } else {
  }

#0 - 0xean

2022-01-17T13:57:05Z

dupe of #137

Findings Information

🌟 Selected for report: WatchPug

Also found by: pauliax, pedroais, robee

Labels

bug
duplicate
G (Gas Optimization)

Awards

18.2633 USDC - $18.26

External Links

Handle

pauliax

Vulnerability details

Impact

Assigned operations to constant variables are re-evaluated every time.

  bytes32 public constant PERMIT_TYPEHASH =
    keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

See https://github.com/ethereum/solidity/issues/9232

Change from 'constant' to 'immutable'.

#0 - 0xean

2022-01-17T13:55:43Z

dupe of #231

Findings Information

🌟 Selected for report: WatchPug

Also found by: defsec, hyh, pauliax

Labels

bug
duplicate
G (Gas Optimization)

Awards

18.2633 USDC - $18.26

External Links

Handle

pauliax

Vulnerability details

Impact

'unchecked' directive can be applied where overflow/underflow is not possible, e.g.:

  require(newBal <= type(uint112).max && newBal > prevBal, "erc");
  uint112 amt = uint112(newBal - prevBal);
  
  require(newBal <= type(uint112).max && newBal > prevBal, "erc");
  uint112 trueDepositAmt = uint112(newBal - prevBal);
  
  require(newBal < type(uint112).max && newBal > prevBal, "erc");
  amount = uint112(newBal - prevBal);

#0 - 0xean

2022-01-17T13:43:07Z

dupe of #238

Findings Information

🌟 Selected for report: pauliax

Labels

bug
G (Gas Optimization)

Awards

100.2104 USDC - $100.21

External Links

Handle

pauliax

Vulnerability details

Impact

I think variable 'amt' in function fundStream can be eliminated if you just re-use the 'amount'. This will save some gas.

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