sherlock-audit / 2024-02-jala-swap-judging

6 stars 4 forks source link

cryptonoob - ChilizWrappedERC20::initialize function doesnt allow tokens with 18 decimals #234

Closed sherlock-admin closed 7 months ago

sherlock-admin commented 7 months ago

cryptonoob

high

ChilizWrappedERC20::initialize function doesnt allow tokens with 18 decimals

Summary

ChilizWrappedERC20::initialize function is used to create a wrapper for an underlying token
However this function only allows tokens less than 18 decimals leaving unable to use the majority of existing tokens because 18 decimals is the most common configuration.

Vulnerability Detail

The vulnerability exists in ChilizWrappedERC20::initialize because it rejects tokens with 18 decimals, the most common configuration for decimals (WETH for example has 18 decimals, some stablecoins like DAI too and even a wrapped chilliz has 18 decimals), so this made unable tokens with this decimals in swap. This is due to the following check in ChilizWrappedERC20::initialize

function initialize(IERC20 _underlyingToken) external {
    // ... snippet  
    if (_underlyingToken.decimals() >= 18) revert InvalidDecimals();

So, if the underlyingToken has 18 decimals it will revert with InvalidDecimals

Impact

The impact of this vulnerability includes:

  1. Not be able to use underlying tokens with 18 decimals.
  2. Possibly loss of market share because it will be unable to swap this tokens. Some non wrapped tokens live deployed on chiliz with 18 decimals are:

The following PoC shows how trying to use a token with 18 decimals will revert Create this test in test sub dir:

// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.10;

import "forge-std/Test.sol";
import "forge-std/console.sol";
import "../contracts/JalaFactory.sol";
import "../contracts/JalaPair.sol";
import "../contracts/JalaRouter02.sol";
import "../contracts/interfaces/IJalaRouter02.sol";
import "../contracts/mocks/ERC20Mintable_decimal.sol";
import "../contracts/mocks/MockWETH.sol";
import "../contracts/JalaMasterRouter.sol";
import "../contracts/utils/ChilizWrapperFactory.sol";
import "../contracts/interfaces/IChilizWrapperFactory.sol";
import "../contracts/libraries/JalaLibrary.sol";

// @add assertions
contract AAAJalaMasterRouter_Test is Test {
    address feeSetter = address(69);
    MockWETH public WETH;

    JalaRouter02 public router;
    JalaMasterRouter public masterRouter;
    JalaFactory public factory;
    IChilizWrapperFactory public wrapperFactory;

    ERC20Mintable public tokenA;
    ERC20Mintable public tokenB;
    ERC20Mintable public tokenC;

    address user0 = vm.addr(0x01);

    function setUp() public {
        WETH = new MockWETH();

        factory = new JalaFactory(feeSetter);
        router = new JalaRouter02(address(factory), address(WETH));
        wrapperFactory = new ChilizWrapperFactory();
        masterRouter = new JalaMasterRouter(address(factory), address(wrapperFactory), address(router), address(WETH));

        tokenA = new ERC20Mintable("Token A", "TKNA", 18);
        tokenB = new ERC20Mintable("Token B", "TKNB", 18);
        tokenC = new ERC20Mintable("Token C", "TKNC", 18);

        vm.deal(address(this), 100 ether);

        tokenA.mint(200 ether, address(this));
        tokenB.mint(200 ether, address(this));
        tokenC.mint(200 ether, address(this));
        tokenA.mint(10000, user0);
        tokenB.mint(10000, user0);
        tokenC.mint(10000, user0);
    }

    function test_AddLiquidityCreatesPair() public {
        tokenA.approve(address(masterRouter), 10000000);
        tokenB.approve(address(masterRouter), 10000000);

        masterRouter.wrapTokensAndaddLiquidity(
            address(tokenA),
            address(tokenB),
            10000000,
            10000000,
            10000000,
            10000000,
            user0,
            block.timestamp
        );
    }
}

Execute with

forge test -vvv --match-contract AAAJalaMasterRouter

Observe it will revert

Code Snippet

https://github.com/sherlock-audit/2024-02-jala-swap/blob/main/jalaswap-dex-contract/contracts/utils/ChilizWrappedERC20.sol#L18-L21

Tool used

Manual Review

Recommendation

Change restriction in ChilizWrappedERC20::initialize function to be able to use tokens with 18 decimals. Ie change decimals check from >= to > in initialize

function initialize(IERC20 _underlyingToken) external {
    if (msg.sender != factory) revert Forbidden();
    if (_underlyingToken.decimals() > 18) revert InvalidDecimals(); // <@ CHANGE >= to >
    if (address(underlyingToken) != address(0)) revert AlreadyExists();

Duplicate of #7