code-423n4 / 2022-01-trader-joe-findings

2 stars 0 forks source link

Gas in `LaunchEvent.sol:createPair()`: `wavaxReserve` should get cached #215

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Handle

Dravee

Vulnerability details

Impact

SLOADs are expensive (~100 gas) compared to MLOADs/MSTOREs (~3 gas). Minimizing them can save gas.

Proof of Concept

The code is as such (see @audit comments):

File: LaunchEvent.sol
377:     function createPair() external isStopped(false) atPhase(Phase.PhaseThree) {
378:         (address wavaxAddress, address tokenAddress) = (
379:             address(WAVAX),
380:             address(token)
381:         );
382:         require(
383:             factory.getPair(wavaxAddress, tokenAddress) == address(0) ||
384:                 IJoePair(
385:                     IJoeFactory(factory).getPair(wavaxAddress, tokenAddress)
386:                 ).totalSupply() ==
387:                 0,
388:             "LaunchEvent: liquid pair already exists"
389:         );
390:         require(wavaxReserve > 0, "LaunchEvent: no wavax balance");//@audit wavaxReserve SLOAD 1
391: 
392:         uint256 tokenAllocated = tokenReserve;
393: 
394:         // Adjust the amount of tokens sent to the pool if floor price not met
395:         if (
396:             floorPrice > (wavaxReserve * 10**token.decimals()) / tokenAllocated //@audit wavaxReserve SLOAD 2
397:         ) {
398:             tokenAllocated = (wavaxReserve * 10**token.decimals()) / floorPrice; //@audit wavaxReserve SLOAD 3
399:             tokenIncentivesForUsers =
400:                 (tokenIncentivesForUsers * tokenAllocated) /
401:                 tokenReserve;
402:             tokenIncentiveIssuerRefund =
403:                 tokenIncentivesBalance -
404:                 tokenIncentivesForUsers;
405:         }
406: 
407:         WAVAX.approve(address(router), wavaxReserve); //@audit wavaxReserve SLOAD 4
408:         token.approve(address(router), tokenAllocated);
409: 
410:         /// We can't trust the output cause of reflect tokens
411:         (, , lpSupply) = router.addLiquidity(
412:             wavaxAddress, // tokenA
413:             tokenAddress, // tokenB
414:             wavaxReserve, // amountADesired //@audit wavaxReserve SLOAD 5
415:             tokenAllocated, // amountBDesired
416:             wavaxReserve, // amountAMin //@audit wavaxReserve SLOAD 6
417:             tokenAllocated, // amountBMin
418:             address(this), // to
419:             block.timestamp // deadline
420:         );
421: 
422:         pair = IJoePair(factory.getPair(tokenAddress, wavaxAddress));
423:         wavaxAllocated = wavaxReserve; //@audit wavaxReserve SLOAD 7
424:         wavaxReserve = 0;
425: 
426:         tokenReserve -= tokenAllocated;
427: 
428:         emit LiquidityPoolCreated(
429:             address(pair),
430:             tokenAddress,
431:             wavaxAddress,
432:             tokenAllocated,
433:             wavaxAllocated
434:         );
435:     }

By caching this in memory and using it, it's possible to save 6 SLOADs

Tools Used

VS Code

Recommended Mitigation Steps

Cache the value in a variable