Trader Joe contest - kirk-baird'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: 7/39

Findings: 4

Award: $2,063.19

🌟 Selected for report: 5

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: kirk-baird

Labels

bug
2 (Med Risk)
sponsor confirmed

Awards

1556.9237 USDT - $1,556.92

External Links

Handle

kirk-baird

Vulnerability details

Impact

The function allowEmergencyWithdraw() may be called by the rocketJoeFactory.owner() at any time. If it is called while the protocol is in Stage 3 and a pair has been created then the LP tokens will be locked and both issues and depositors will be unable to withdraw.

Proof of Concept

If allowEmergencyWithdraw() is called stopped is set to true. As a result functions withdrawIncentives() and withdrawLiquidity() will revert due to the isStopped(false) modifier reverting.

Additionally, emergencyWithdraw() will revert since all the WAVAX and token balances have been transferred to the liquidity pool.

Thus, depositors and issuers will have no methods of removing their LP tokens or incentives.

Consider adding the requirement require(address(pair) != address(0), "LaunchEvent: pair not created"); to the function allowEmergencyWithdraw().

#0 - cryptofish7

2022-02-01T00:56:09Z

Findings Information

🌟 Selected for report: kirk-baird

Also found by: 0v3rf10w, static

Labels

bug
2 (Med Risk)
disagree with severity
sponsor confirmed

Awards

420.3694 USDT - $420.37

External Links

Handle

kirk-baird

Vulnerability details

Impact

Note: this attack requires rJoe to relinquish control during tranfer() which under the current RocketJoeToken it does not. Thus this vulnerability is raised as medium rather than high. Although it's not exploitable currently, it is a highly risky code pattern that should be avoided.

This vulnerability would allow the entire rJoe balance to be drained from the contract.

Proof of Concept

The function deposit() would be vulnerable to reentrancy if rJoe relinquished control flow.

The following lines show the reward calculations in variable pending. These calculations use two state variables user.amount and user.rewardDebt. Each of these are updated after _safeRJoeTransfer().

Thus if an attacker was able to get control flow during the rJoe::tranfer() function they would be able to reenter deposit() and the value calculated for pendingwould be the same as the previous iteration hence they would again be transferred pending rJoe tokens. During the rJoe transfer the would again gain control of the execution and call deposit() again. The process could be repeated until the entire rJoe balance of the contract has been transferred to the attacker.

        if (user.amount > 0) {
            uint256 pending = (user.amount * accRJoePerShare) /
                PRECISION -
                user.rewardDebt;
            _safeRJoeTransfer(msg.sender, pending);
        }
        user.amount = user.amount + _amount;
        user.rewardDebt = (user.amount * accRJoePerShare) / PRECISION;

Tools Used

n/a

There are two possible mitigations. First is to use the openzeppelin reentrancy guard over the deposit() function which will prevent multiple deposits being made simultaneously.

The second mitigation is to follow the checks-effects-interactions pattern. This would involve updating all state variables before making any external calls.

#0 - cryptofish7

2022-01-31T20:06:58Z

#1 - dmvt

2022-02-22T13:18:43Z

I agree with the warden's assessment of risk on this one. Leaving it unaddressed would represent a potential future compromise if it was forgotten about by the team.

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