38335 [SC-Medium] attacker can exploit partnervault mint small amount to cause lbtc depeg or protocol insolvency
#38335 [SC-Medium] Attacker can exploit PartnerVault mint small amount to cause LBTC depeg or Protocol Insolvency
Submitted on Dec 31st 2024 at 11:21:55 UTC by @perseverance for Audit Comp | Lombard
Report ID: #38335
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/lombard-finance/evm-smart-contracts/blob/main/contracts/fbtc/PartnerVault.sol
Impacts:
Permanent freezing of funds
Protocol insolvency
Description
Description
Brief/Intro
User can permissionless (no permission) to use PartnertVault to mint LockedFBTC by using function
https://github.com/lombard-finance/evm-smart-contracts/blob/main/contracts/fbtc/PartnerVault.sol#L182-L184
By doing this, user will transfer the FBTC to the PartnerVault contract. FBTC then will be sent to LockedFBTC of FBTC contract to burn FBTC.
https://github.com/fbtc-com/fbtcX-contract/blob/main/src/LockedFBTC.sol#L117-L134
Then it will invoke addBurnRequest of FireBridge
https://github.com/fbtc-com/fbtc-contract/blob/main/contracts/FireBridge.sol#L287-L322
To summarize the fund flow is below:
The vulnerability
Vulnerability Details
The bug here is ParnerVault does not check if the amount is below Dust Limit on Bitcoin. It does check if amount is not Zero.
This DustLimit is related to Dust that is defined in terms of dustRelayFee, which has units satoshis-per-kilobyte. If users pay more in fees than the value of the output to spend something, then Bitcoin consider it dust. See Reference
So if the amount after fee is less than the DustLimit on BitcoinBitcoin, then the output amount can not be spent.
https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp#L28-L41
So it depends on the type of user withdrawal address type.
For the new address types: P2WPKH, P2TR, P2WSH and the default rate fee is 3000 satoshi per kilobyte, then the DustLimit is 294 satoshi. But for old address types, the DustLimit can be 546 satoshi as commented above.
So as I don't know the type of Lombard PartnerVault withdrawal type of address, let's assume that it is one of the modern types: P2WPKH, P2TR, P2WSH so the Dust Level is 294 according to Bitcoin documentation. Let's take a value of 291 for example.
The FBTC Firebridge contract also does not check if amount is below Dust Limit. It is the responsibility of users to check that.
So if user input amount that less than Dust Limit on Bitcoin
There are 2 scenarios:
If FBTC system confirm the burn request, then the withdrawal output on Bitcoin cannot be spent.
Or if the FBTC does not confirm that burn request, then the FBTC is lost and Lombard will not receive any Bitcoin.
So now an attacker can exploit this to cause depeg or freeze of fund.
Attack scenario:
Step 1: Attacker repeats 10_000 times the call mint(291) in PartnerVault
User spent 10_000 * 291 FBTC = 2_910_000 FBTC
User received 2_910_000 LBTC
Step 2: Attacker using some exchange to convert LBTC to FBTC and repeat step 1. Suppose the fee is 5%
User received 2_764_500
user repeated the attack in step 1: user received 2_764_500 LBTC
Step 3: continued to do this attack
So with very small amount of capital and just gas to execute the attack, the attacker will cause the impact:
Lombard will mint LBTC. With each mint, the LBTC total_supply is increased
Lombard received LockedFBTC.
Lombard either will not receive Bitcoin or receive the Bitcoin that will not be spent.
Lombard cannot redeem this LockedFBTC token, because to redeem it, Lombard need to deposit into FBTC to initializeBurn in PartnerVault.
Impacts
About the severity assessment
Bug Severity: Critical
Impact category:
Attacker's capital: Small amount of FBTC and pay gas to execute the attack
So with repeated attacks, attacker can cause:
The amount of LBTC that was minted is much bigger than the total of Bitcoin that can be spent.
This caused impact:
Protocol Insolvecy
Depeg of LBTC
Freeze of funds on Bitcoin
Proof of Concept
Proof of concept
Steps to reproduce the bug:
Step 1: Attacker repeats 10_000 times the call mint(291) in PartnerVault
User spent 10_000 * 291 FBTC = 2_910_000 FBTC User received 2_910_000 LBTC
The test code to show this bug:
Just copy the test case into test suite "FBTC locking" in evm-smart-contracts\test\PartnerVault.ts
To run the test
Test log:
Explanation:
In this case, I call mint 10_000 times in the test case, but to exploit attacker can deploy an attack contract to repeat the mint() in the exploit contract. But the attack scenario is the same, so I use this test to show the attack.
Step 2: Attacker using some exchange to convert LBTC to FBTC and repeat step 1. Suppose the fee is 5%
Attacker received 2_764_500 Attacker repeated the attack in step 1: Attacker received 2_764_500 LBTC
Step 3: continued to do this attack
Was this helpful?