#38116 [SC-Insight] Partner vaults don't account for FireBridge fees, forcing LBTC burn to never wor

Submitted on Dec 24th 2024 at 21:30:49 UTC by @OxAlix2 for Audit Comp | Lombard

  • Report ID: #38116

  • Report Type: Smart Contract

  • Report severity: Insight

  • Target: https://github.com/lombard-finance/evm-smart-contracts/blob/main/contracts/fbtc/PartnerVault.sol

  • Impacts:

    • Permanent freezing of funds

    • Protocol insolvency

Description

Brief/Intro

Users can use partner vaults to deposit their FBTC tokens and get LBTC in return. The reverse is also possible by burning the LBTC tokens in return for FBTC tokens, this is done by the partner vaults calling LockedFBTC, which in return calls FireBridge to finalize the withdrawal, which charges some fees. On the other hand, the withdrawal operation has a unique key represented as the hash of the following: recipient, amount, depositTxId, and outputIndex. However, this doesn't account for the fees that the FireBridge charges.

Vulnerability Details

To get FBTC back there's a step process that should be made, first is calling initializeBurn, while providing the needed amount to withdraw, the key is later created according to:

bytes32 key = keccak256(
    abi.encode(recipient, amount, depositTxId, outputIndex)
);

At a later stage in the function, lockedFbtc.redeemFbtcRequest is called which initiates a redeem operation, https://github.com/lombard-finance/evm-smart-contracts/blob/main/contracts/fbtc/PartnerVault.sol#L239-L243. LockedFBTC later calls IFireBridge(fbtcBridge).addMintRequest which constructs the redemption request, the issue here is that this doesn't return the exact amount but amount - fees:

The returned request amount gets saved:

The issue here is that the amount used in the key is not equal to request.amount

Later, when finalizeBurn is called it'll always revert:

Impact Details

This blocks users from swapping their LBTC back to FBTC, which ultimately forces users to lose their FBTC.

References

  • LockedFBTC: https://etherscan.io/address/0x8dc0d5e06995d119a9ccdb3472cc9e920389f39c#code

  • FireBridge: https://etherscan.io/address/0xc5e2f85cb57350d3ae918d8b038f891f8ed6f6e5#code

  • https://github.com/lombard-finance/evm-smart-contracts/blob/main/contracts/fbtc/PartnerVault.sol#L231-L233

  • https://github.com/lombard-finance/evm-smart-contracts/blob/main/contracts/fbtc/PartnerVault.sol#L269-L270

Mitigation

Used the amount returned from the LockedFBTC as the amount in the withdrawal key.

Proof of Concept

Proof of Concept

To demonstrate the case where fees are >0, we need to apply the following change to contracts/mock/LockedFBTCMock.sol:

Add the following test in test/PartnerVault.ts in FBTCPartnerVault:

Last updated

Was this helpful?