Abstract
Velocore experienced a security breach on June 2nd, 2024, resulting in financial losses approximating $6.8 million in ETH. The root cause of this compromise was due to vulnerabilities within the Balancer-style CPMM pool contract. We would like to thank Niv from Hexagate for first reporting the issue and setting up a group chat with our Mods. Also Great thanks to Gal of Hypernative and Ironblock for quickly setting up a war room and assisting in the investigation.
Affected Contracts
- All volatile pools(CPMM) in Linea and zkSyncEra Velocore are affected.
- No stable pools are affected.
- Telos Velocore shared the same vulnerabilities, but we mitigated the issue before it was exploited.
- Blade, an advanced fork of Velocore, does not share this vulnerability as it uses simple XYK pool instead of our CPMM pool.
Smart Contract Vulnerability Analysis
The primary cause of the incident was faulty logic within the ‘velocore__execute()’ function of the ConstantProductPool. When a user makes a swap on Velocore, the Vault contract makes an external call to this function to calculate the result of the swap.
Vulnerability in Fee Rate Calculation Logic
The ‘feeMultiplier’ is a variable in ‘ConstantProductPool’ that increases whenever a withdrawal occurs and resets to 1 after a block. This multiplier was introduced to prevent bypassing fees by withdrawing and then depositing, effectively making a swap without fees. This factor gets multiplied with the fee rate to calculate the actual fee (‘effectiveFee1e9’).
uint256 effectiveFee1e9 = fee1e9;
if (lastWithdrawTimestamp == block.timestamp) {
unchecked {
effectiveFee1e9 = (effectiveFee1e9 * feeMultiplier) / 1e9;
}
}
The vulnerability here is that `effectiveFee1e9` was allowed to exceed 100%, causing subsequent logic to malfunction.
Underflow Potential During Single-Token Withdrawal
Velocore allows users to withdraw LP into a single token. As this is effectively a swap from the other tokens into one token, the calculation involves applying a fee to the other tokens:
unchecked {
uint256 unaccountedFeeAsGrowth1e18 = k >= 1e18
? 1e18
: rpow(1e18 - ((1e18 - k) * effectiveFee1e9) / 1e9, _sumWeight - sumUnknownWeight - sumKnownWeight, 1e18);
requestedGrowth1e18 = (requestedGrowth1e18 * unaccountedFeeAsGrowth1e18) / 1e18;
}
- `k` is the liquidity growth rate; a value greater than 1e18 indicates a deposit, and less than 1e18 indicates a withdrawal.
- `unaccountedFeeAsGrowth1e18` is the fee factor, supposed to be between 0 and 1e18, inclusive. This value represents liquidity shrinkage after withdrawing fees.
- `requestedGrowth1e18` is `k * unaccountedFeeAsGrowth1e18`, representing overall liquidity change used for calculating actual token in/out amounts. - The problem is that `effectiveFee1e9` being greater than 100% can cause `1e18 — ((1e18 — k) * effectiveFee1e9)` to underflow, changing a withdrawal into a large deposit.
Lack of Caller Checking in `velocore__execute`
There was an additional vulnerability where `velocore__execute()` does not verify whether the caller is the Vault or not. This made the exploit easier, though the attack would have been possible without this flaw.
Actual Exploit
The attacker sourced funds from Tornado, executed the exploit, bridged the funds with Across Bridge, and then deposited them back into Tornado.
The attacker first directly called `velocore__execute()`, simulating large withdrawals. This caused the `feeMultiplier` to increase to the point where `effectiveFee1e9` became greater than 100%.The attacker then used a flash loan to obtain LP tokens and withdrew most of the tokens with them, contracting the pool size.
Finally, the attacker performed a small single-token withdrawal, which minted an abnormally large amount of LP tokens due to the underflow mentioned above, allowing the attacker to repay the flash loan.
Relevant Transactions and Addresses :
Final fund destination — 0xe4062fcade7ac0ed47ad794028967a2314ee02b3
EOA —
0x8cdc37ed79c5ef116b9dc2a53cb86acaca3716bf
0xd8c465ecd8c6f1a0c114890f1ef553f82e59d274
Contracts —
0xed4e130f6f9e68918996f7e1e46a3306b3e12cec
0xb7f6354b2cfd3018b3261fbc63248a56a24ae91a
0xc030fba4b741b770f03e715c3a27d02c41fc9dae
0xf7f76b30a301524fe76508546B1e3762eF2B9267
Txs — Tx1 Tx2 zksync
Mitigation
We received a critical security alert from Cyvers after the first Linea exploit. Since we revoked our admin rights from the vault last year, we couldn’t upgrade the proxy to completely block transactions. Instead, we implemented a semi-pause function by setting the fee to the maximum, which would interrupt swaps while allowing withdrawals in case of an emergency. However, in this case, the proper mitigation was to set the fee to 0%, not to max. Unfortunately, we realized this only after reverse-engineering the transactions, and by then, it was too late.
To mitigate the issue and prevent further damage, we have set the fee to 0 for all pools. Consequently, the ‘effectiveFee1e9’ value will always be 0, effectively disabling the vulnerability described above. This measure ensures that the exploit cannot be leveraged anymore.
Next Steps
Despite undergoing multiple audits and implementing preventive features to ensure security, this unexpected incident happened swiftly. We are deeply saddened and sincerely apologize to our users who have trusted us.
In light of the recent incident impacting our protocol, Velocore is committed to taking comprehensive measures to resolve the situation and ensure the security and trust of our users.
We are actively investigating to track down hackers while trying the on-chain negotiation, having requested cooperation from various protocols and central exchanges to investigate the attacker’s activities. We are also in close communication with our security partners and foundations. Based on the results of these investigations and our collaboration with partners, we will continuously adjust our future plans.
For those affected, we have taken a snapshot of the blockchain state prior to the incident. Once operations resume, we will implement an appropriate compensation plan to address the losses incurred to our users. We understand the importance of transparency and fairness in these times and are dedicated to providing clear and effective solutions.
Our goal is not only to resolve this issue but also to enhance the protocol’s security measures, rebuild trust, and minimize the damage.