Revert Lend - tpiliposian's results

A lending protocol specifically designed for liquidity providers on Uniswap v3.

General Information

Platform: Code4rena

Start Date: 04/03/2024

Pot Size: $88,500 USDC

Total HM: 31

Participants: 105

Period: 11 days

Judge: ronnyx2017

Total Solo HM: 7

Id: 342

League: ETH

Revert

Findings Distribution

Researcher Performance

Rank: 78/105

Findings: 1

Award: $42.78

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

42.7786 USDC - $42.78

Labels

bug
downgraded by judge
grade-a
high quality report
QA (Quality Assurance)
:robot:_17_group
duplicate-366
Q-42

External Links

Lines of code

https://github.com/code-423n4/2024-03-revert-lend/blob/435b054f9ad2404173f36f0f74a5096c894b12b7/src/transformers/LeverageTransformer.sol#L40-L96 https://github.com/code-423n4/2024-03-revert-lend/blob/435b054f9ad2404173f36f0f74a5096c894b12b7/src/transformers/LeverageTransformer.sol#L123-L175

Vulnerability details

Impact

The LeverageTransformer.sol contract has leverageUp and leverageDown functions, which are intended to be called from the V3Vault.sol contract. However, the mentioned functions lack proper msg.sender validation, which allows malicious contracts to call those functions and steal stuck funds on the contract.

Proof of Concept

For a malicious contract to steal stuck funds, the following things must be true about the state of the contract.

  1. There must be an NFT in the nonfungiblePossitionManager with the tokens that the attacker wants to steal.
  2. One of two tokens of the position NFT must be stuck on the contract. If those two things are true the attacker can create a malicious contract with the function asset() and borrow() and call the leverageUp or leverageDown function through the malicious contract in a way that enables them to steal the stuck funds.
    function leverageUp(LeverageUpParams calldata params) external {
        uint256 amount = params.borrowAmount;

        address token = IVault(msg.sender).asset();

        IVault(msg.sender).borrow(params.tokenId, amount);

[...]

        // send leftover tokens
        if (amount0 > added0) {
            SafeERC20.safeTransfer(IERC20(token0), params.recipient, amount0 - added0);
        }
        if (amount1 > added1) {
            SafeERC20.safeTransfer(IERC20(token1), params.recipient, amount1 - added1);
        }
        if (token != token0 && token != token1 && amount > 0) {
            SafeERC20.safeTransfer(IERC20(token), params.recipient, amount);
        }
    }
    function leverageDown(LeverageDownParams calldata params) external {
        address token = IVault(msg.sender).asset();

[...]

        IVault(msg.sender).repay(params.tokenId, amount, false);

        // send leftover tokens
        if (amount0 > 0 && token != token0) {
            SafeERC20.safeTransfer(IERC20(token0), params.recipient, amount0);
        }
        if (amount1 > 0 && token != token1) {
            SafeERC20.safeTransfer(IERC20(token1), params.recipient, amount1);
        }
    }

Tools Used

Manual review.

Consider adding a mechanism for checking the msg.sender and the following check in the code:

require( msg.sender == Vaultaddr )

Assessed type

Invalid Validation

#0 - c4-pre-sort

2024-03-16T10:10:03Z

0xEVom marked the issue as duplicate of #366

#1 - c4-pre-sort

2024-03-18T08:49:15Z

0xEVom marked the issue as high quality report

#2 - 0xEVom

2024-03-18T09:14:13Z

Clear description of the issue, points out both leverageUp and leverageDown

Mentions precondition:

One of two tokens of the position NFT must be stuck on the contract.

#3 - c4-judge

2024-03-29T01:44:21Z

jhsagd76 changed the severity to QA (Quality Assurance)

#4 - c4-judge

2024-03-29T01:45:37Z

jhsagd76 marked the issue as grade-a

#5 - jhsagd76

2024-03-29T01:45:48Z

L-A

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