Trader Joe contest - defsec's results

One-stop-shop decentralized trading on Avalanche.

General Information

Platform: Code4rena

Start Date: 25/01/2022

Pot Size: $50,000 USDT

Total HM: 17

Participants: 39

Period: 3 days

Judge: LSDan

Total Solo HM: 9

Id: 79

League: ETH

Trader Joe

Findings Distribution

Researcher Performance

Rank: 3/39

Findings: 4

Award: $2,598.45

🌟 Selected for report: 3

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: cmichel

Also found by: Czar102, Ruhum, Tomio, WatchPug, defsec, hack3r-0m, hyh, saian

Labels

bug
duplicate
2 (Med Risk)

Awards

74.4672 USDT - $74.47

External Links

Handle

defsec

Vulnerability details

Impact

The call to transferFrom is done without checking the results. For certain ERC20 tokens, if insufficient tokens are present, no revert occurs but a result of “false” is returned. It’s important to check this. If you don’t, in this concrete case, some airdrop eligible participants could be left without their tokens. It is also a best practice to check this.

Proof of Concept

  1. Navigate to the following contract.
https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L133
  1. It is good to add a require() statement that checks the return value of token transfers or to use something like OpenZeppelin’s safeTransfer/safeTransferFrom unless one is sure the given token reverts in case of a failure. Failure to do so will cause silent failures of transfers and affect token accounting in contract.

Tools Used

Code Review

Check the result of transferFrom and transfer. Although if this is done, the contracts will not be compatible with non standard ERC20 tokens like USDT. For that reason, I would rather recommend making use of SafeERC20 library: safeTransfer and safeTransferFrom.

#0 - cryptofish7

2022-01-31T00:51:31Z

Duplicate of #232

#1 - dmvt

2022-02-22T19:26:18Z

duplicate of #198

Findings Information

🌟 Selected for report: defsec

Labels

bug
2 (Med Risk)
sponsor disputed

Awards

1556.9237 USDT - $1,556.92

External Links

Handle

defsec

Vulnerability details

Impact

The TraderJOE protocol do not appear to support rebasing/deflationary/inflationary tokens whose balance changes during transfers or over time. The necessary checks include at least verifying the amount of tokens transferred to contracts before and after the actual transfer to infer any fees/interest.

Proof of Concept

https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeStaking.sol#L133

https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L132

Tools Used

Code Review

  • Ensure that to check previous balance/after balance equals to amount for any rebasing/inflation/deflation
  • Add support in contracts for such tokens before accepting user-supplied tokens
  • Consider supporting deflationary / rebasing / etc tokens by extra checking the balances before/after or strictly inform your users not to use such tokens if they don't want to lose them.

#0 - cryptofish7

2022-02-01T15:07:02Z

It won’t revert as long as token’s balance doesn’t decrease (this never happens)

#1 - dmvt

2022-02-23T12:47:09Z

It is possible for someone to unknowingly use this functionality with a token that rebases down during the launch event. Just because you don't support a token type, doesn't mean that the design doesn't exist. This is a medium risk, not a low risk, because the is the potential for external interaction to cause a loss of funds.

Findings Information

🌟 Selected for report: defsec

Labels

bug
1 (Low Risk)
sponsor confirmed

Awards

518.9746 USDT - $518.97

External Links

Handle

defsec

Vulnerability details

Impact

During the code review, It has been observed that the token can be same as WAVAX. The initialize function should not allow if token is equals to wavax. That would affect all asset management.

Proof of Concept

  1. Navigate to the following contract.
https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L219 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L411

Tools Used

Code Review

On the Launchevent, token should not be equal to wavax.

#0 - cryptofish7

2022-01-31T23:22:43Z

Findings Information

🌟 Selected for report: cccz

Also found by: Czar102, Jujic, Meta0xNull, Ruhum, defsec, jayjonah8, kirk-baird, p4st13r4, pauliax, robee, wuwe1

Labels

bug
duplicate
1 (Low Risk)

Awards

13.5716 USDT - $13.57

External Links

Handle

defsec

Vulnerability details

Impact

All contract initializers were missing access controls, allowing any user to initialize the contract. By front-running the contract deployers to initialize the contract, the incorrect parameters may be supplied, leaving the contract needing to be redeployed.

Proof of Concept

  1. Navigate to the following contracts.
https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeStaking.sol#L57
  1. initialize functions does not have access control. They are vulnerable to front-running.

Tools Used

Manual Code Review

While the code that can be run in contract constructors is limited, setting the owner in the contract's constructor to the msg.sender and adding the onlyOwner modifier to all initializers would be a sufficient level of access control.

#0 - cryptofish7

2022-01-30T23:37:05Z

Duplicate of #8

Findings Information

🌟 Selected for report: cccz

Also found by: defsec

Labels

bug
duplicate
1 (Low Risk)

Awards

233.5386 USDT - $233.54

External Links

Handle

defsec

Vulnerability details

Impact

"RocketJoeToken.sol", "RocketJoeFactory" and "RocketJoeStaking" inherit OpenZeppelin's Ownable contract which enables the onlyOwner role to transfer ownership to another address. It's possible that the onlyOwner role mistakenly transfers ownership to the wrong address, resulting in a loss of the onlyOwner role. The current ownership transfer process involves the current owner calling Unlock.transferOwnership(). This function checks the new owner is not the zero address and proceeds to write the new owner's address into the owner's state variable. If the nominated EOA account is not a valid account, it is entirely possible the owner may accidentally transfer ownership to an uncontrolled account, breaking all functions with the onlyOwner() modifier. Lack of two-step procedure for critical operations leaves them error-prone if the address is incorrect, the new address will take on the functionality of the new role immediately

for Ex : -Alice deploys a new version of the whitehack group address. When she invokes the whitehack group address setter to replace the address, she accidentally enters the wrong address. The new address now has access to the role immediately and is too late to revert

Proof of Concept

  1. Navigate to "https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeToken.sol#L12", "https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L18" and "https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeStaking.sol#L14"
  2. The contracts have many onlyOwner function.
  3. The contract is inherited from the Ownable which includes transferOwnership.

Tools Used

None

Implement zero address check and Consider implementing a two step process where the owner nominates an account and the nominated account needs to call an acceptOwnership() function for the transfer of ownership to fully succeed. This ensures the nominated EOA account is a valid and active account.

#0 - cryptofish7

2022-01-31T11:13:56Z

Duplicate of #10

Findings Information

🌟 Selected for report: cccz

Also found by: csanuragjain, defsec, robee

Labels

bug
duplicate
1 (Low Risk)

Awards

94.5831 USDT - $94.58

External Links

Handle

defsec

Vulnerability details

Impact

Some tokens (like USDT L199) do not work when changing the allowance from an existing non-zero allowance value. They must first be approved by zero and then the actual allowance must be approved.

IERC20(token).approve(address(operator), 0); IERC20(token).approve(address(operator), amount);

Proof of Concept

  1. Navigate to the following contracts.
https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/LaunchEvent.sol#L408
  1. When trying to re-approve an already approved token, all transactions revert and the protocol cannot be used.

Tools Used

None

Approve with a zero amount first before setting the actual amount.

#0 - cryptofish7

2022-01-31T14:31:50Z

Duplicate of #22

Findings Information

🌟 Selected for report: Dravee

Also found by: 0x1f8b, WatchPug, bobi, defsec, pauliax

Labels

bug
duplicate
1 (Low Risk)

Awards

51.0749 USDT - $51.07

External Links

Handle

defsec

Vulnerability details

Impact

The following contract functions performs an ERC20.approve() call but does not check the success return value. Some tokens do not revert if the approval failed but return false instead.

Proof of Concept

  1. Navigate to the following contracts.
https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/LaunchEvent.sol#L408
  1. Tokens that don't actually perform the approve and return false are still counted as a correct approve.

Tools Used

None

Its recommend to using OpenZeppelin’s SafeERC20 versions with the safeApprove function that handles the return value check as well as non-standard-compliant tokens.

Reference : https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.1/contracts/token/ERC20/utils/SafeERC20.sol#L74

#0 - cryptofish7

2022-01-31T14:32:11Z

Duplicate of #154

Findings Information

🌟 Selected for report: sirhashalot

Also found by: 0v3rf10w, 0x1f8b, Dravee, UncleGrandpa925, cccz, defsec, gzeon

Labels

bug
duplicate
1 (Low Risk)

Awards

31.028 USDT - $31.03

External Links

Handle

defsec

Vulnerability details

Impact

Missing checks for zero-addresses may lead to infunctional protocol, if the variable addresses are updated incorrectly.

Proof of Concept

  1. Navigate to the following contracts.
https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L158 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L171 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L178 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L185 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L192 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L218

Tools Used

Code Review

Consider adding zero-address checks in the discussed constructors: require(newAddr != address(0));.

#0 - cryptofish7

2022-01-31T00:52:27Z

Duplicate of #263

Findings Information

🌟 Selected for report: WatchPug

Also found by: 0x0x0x, Czar102, Dravee, Jujic, Meta0xNull, Ruhum, byterocket, defsec, gzeon, pedroais, robee, solgryn

Labels

bug
duplicate
G (Gas Optimization)

Awards

0.8642 USDT - $0.86

External Links

Handle

defsec

Vulnerability details

Vulnerability details

Impact

!= 0 is a cheaper operation compared to > 0, when dealing with uint.

Proof of Concept

  1. Navigate to the following contracts.
https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L338 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L355 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L370 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L390 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L486 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L498 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeStaking.sol#L101

Tools Used

Code Review

Use "!=0" instead of ">0" for the gas optimization.

#0 - cryptofish7

2022-01-30T23:49:25Z

Duplicate of #240

Findings Information

🌟 Selected for report: WatchPug

Also found by: Czar102, Dravee, Jujic, Meta0xNull, byterocket, defsec, p4st13r4, pauliax, robee, sirhashalot

Labels

bug
duplicate
G (Gas Optimization)

Awards

1.2609 USDT - $1.26

External Links

Handle

defsec

Vulnerability details

Impact

Shortening revert strings to fit in 32 bytes will decrease deploy time gas and will decrease runtime gas when the revert condition has been met.

Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.

Proof of Concept

Revert strings > 32 bytes are here:

https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L311

https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/LaunchEvent.sol#L621

https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeFactory.sol#L224

Tools Used

Manual Review

Shorten the revert strings to fit in 32 bytes. That will affect gas optimization.

#0 - cryptofish7

2022-01-31T11:51:34Z

Duplicate of #242

Findings Information

🌟 Selected for report: WatchPug

Also found by: Dravee, Jujic, Rhynorater, TomFrenchBlockchain, defsec, hyh, ye0lde

Labels

bug
duplicate
G (Gas Optimization)

Awards

2.3783 USDT - $2.38

External Links

Handle

defsec

Vulnerability details

Impact

For the arithmetic operations that will never over/underflow, using the unchecked directive (Solidity v0.8 has default overflow/underflow checks) can save some gas from the unnecessary internal over/underflow checks.

Proof of Concept

https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeStaking.sol#L167 https://github.com/code-423n4/2022-01-trader-joe/blob/main/contracts/RocketJoeStaking.sol#L87

Tools Used

None

Consider applying unchecked arithmetic where overflow/underflow is not possible.

#0 - cryptofish7

2022-01-31T00:06:03Z

Duplicate of #233

Findings Information

🌟 Selected for report: defsec

Also found by: Tomio

Labels

bug
disagree with severity
G (Gas Optimization)
sponsor confirmed

Awards

17.9007 USDT - $17.90

External Links

Handle

defsec

Vulnerability details

Impact

In the JoeStaking contract, the amount check should be placed on the contract. IF the amount is more than transfer operations should be completed.

Proof of Concept

  1. Navigate to the following contract.

https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/RocketJoeStaking.sol#L129

  1. _amount is not checked if Its more than zero.
function withdraw(uint256 _amount) external { UserInfo storage user = userInfo[msg.sender]; require( user.amount >= _amount, "RocketJoeStaking: withdraw amount exceeds balance" ); updatePool(); uint256 pending = (user.amount * accRJoePerShare) / PRECISION - user.rewardDebt; user.amount = user.amount - _amount; user.rewardDebt = (user.amount * accRJoePerShare) / PRECISION; _safeRJoeTransfer(msg.sender, pending); joe.safeTransfer(address(msg.sender), _amount); emit Withdraw(msg.sender, _amount); }

Tools Used

Code Review

Consider to add the following check.

function withdraw(uint256 _amount) external { UserInfo storage user = userInfo[msg.sender]; require( user.amount >= _amount, "RocketJoeStaking: withdraw amount exceeds balance" ); updatePool(); uint256 pending = (user.amount * accRJoePerShare) / PRECISION - user.rewardDebt; user.amount = user.amount - _amount; user.rewardDebt = (user.amount * accRJoePerShare) / PRECISION; if(pending != 0) { _safeRJoeTransfer(msg.sender, pending); } if(_amount != 0){ joe.safeTransfer(address(msg.sender), _amount); } emit Withdraw(msg.sender, _amount); }

#0 - cryptofish7

2022-01-31T20:16:49Z

Disagree with severity, as it won't revert, but there is gas optimisation.

Fix: https://github.com/traderjoe-xyz/rocket-joe/pull/146

#1 - dmvt

2022-02-21T13:08:26Z

Agree with sponsor, this is a gas optimization.

Findings Information

🌟 Selected for report: hyh

Also found by: Czar102, Dravee, Jujic, bobi, byterocket, defsec, jayjonah8, p4st13r4

Labels

bug
duplicate
G (Gas Optimization)

Awards

1.9026 USDT - $1.90

External Links

Handle

defsec

Vulnerability details

Impact

Using newer compiler versions and the optimizer gives gas optimizations and additional safety checks are available for free.

The advantages of versions 0.8.* over <0.8.0 are:

  • Safemath by default from 0.8.0 (can be more gas efficient than library based safemath.)
  • Low level inliner : from 0.8.2, leads to cheaper runtime gas. Especially relevant when the contract has small functions. For example, OpenZeppelin libraries typically have a lot of small helper functions and if they are not inlined, they cost an additional 20 to 40 gas because of 2 extra jump instructions and additional stack operations needed for function calls.
  • Optimizer improvements in packed structs: Before 0.8.3, storing packed structs, in some cases used an additional storage read operation. After EIP-2929, if the slot was already cold, this means unnecessary stack operations and extra deploy time costs. However, if the slot was already warm, this means additional cost of 100 gas alongside the same unnecessary stack operations and extra deploy time costs.
  • Custom errors from 0.8.4, leads to cheaper deploy time cost and run time cost. Note: the run time cost is only relevant when the revert condition is met. In short, replace revert strings by custom errors.

Proof of Concept

  1. The contest repository contracts contain floating pragma ^0.8.0. The contracts pragma version can be updated to 0.8.4 for the gas optimization.
  • Affected Contracts

All Contracts

Tools Used

None

Consider to upgrade pragma to at least 0.8.4.

#0 - cryptofish7

2022-02-11T00:33:55Z

Duplicate of #181

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