Full Report
Acala is an L2 blockchain built around the Polkadot ecosystem. Polkadot acts as the relay chain which coordinates with other blockchains in the network. Acala, in this system, is referenced to as a "Parachain". The parachain is able to create lots of custom functionality for their needs. On a Parachain, there are para-validators. These validators are responsible for block creation and block finalization on a specific block. Home module specific to Acala is the Homa module. Homa is a Tokenized Liquid Staking Protocol. The idea is that DOT (Polkadot tokens) could be put into the module and a representation called LDOT returned to the user. Everyone wins - the protocol has more funds to use in staking, the user gets a little bit of that profit and the user is able to use LDOT on the blockchain for other things. If a user wants to withdraw their DOT token, the user submit an unbond request. Every 24 hours all of the unbond requests are processed at once. The vulnerability is something relatively simple but complicated to know if it's exploitable: a missing size limit on the amount of unbond requests. Since this list of unbounded (see what I did there), it can be filled up and force the blockchain to process too many in a single call. There's just a big loop that it iterates over. When I see vulnerabilities like this, I think "PoC or GTFO". Is this actually exploitable? In reality, it is! The blog post says that Acala blocks have a time limit and if this isn't met then the chain halts. By creating 22K withdrawal requests, it slows down the chain enough to prevent the block from being created. The payout was interesting to me. According to Immunefi, a Governance proposal takes 15 days to go through on Acala - meaning that a downtime of 15 days is likely because the proposal is required for the upgrade. Additionally, DefiLlama has a 15 day volume of 712K per day. Given that the payout should be 10% of that, the whitehat got 10% of it. To me, this calculate is strange. If a chain was indeed really down the governance would pass significantly faster. Additionally, a denial of service paying 10% of funds at risk is weird to me; it's an L1 that can fix the chain. The funds were never permanently stuck, like if it was a smart contract that couldn't be changed. A good bug, a good payout and a good writeup!
Analysis Summary
# Vulnerability: Block Production Halt via Unbounded Redeem Requests in Homa Module
## CVE Details
- **CVE ID**: Not Assigned (Typical for Web3/Substrate vulnerabilities reported via bug bounties)
- **CVSS Score**: Estimated 7.5 (High) - Primary impact is Availability
- **CWE**: CWE-400: Uncontrolled Resource Consumption ("Resource Exhaustion")
## Affected Systems
- **Products**: Acala Network (Polkadot Parachain)
- **Versions**: Versions prior to Pull Request [#2806](https://github.com/AcalaNetwork/Acala/pull/2806)
- **Configurations**: Systems running the `Homa` module (Tokenized Liquid Staking Protocol)
## Vulnerability Description
The vulnerability exists within the `process_redeem_requests` function of the Homa module. In the Acala ecosystem, users submit "unbond" requests to redeem DOT from LDOT. These requests are stored in a map and processed collectively every ~24 hours via the `on_initialize` hook.
The root cause is a **missing size limit** on the number of requests the validator attempts to process in a single block. The code utilizes a `for` loop to iterate over the `RedeemRequests` map. Because there is no cap on the iterations, an attacker can flood the map with thousands of small requests. When the `on_initialize` function is triggered, the execution time exceeds the mandatory block production time limit (weight limit) assigned to the parachain, causing the network to fail block finalization and halt.
## Exploitation
- **Status**: PoC available/Verified (Disclosed via Immunefi)
- **Complexity**: Low
- **Attack Vector**: Network (Requires creating multiple accounts/requests on-chain)
An attacker can create approximately 22,000 withdrawal requests from different accounts. This volume is sufficient to slow down the `on_initialize` execution beyond the Polkadot relay chain's allowed execution window for a parachain block, successfully halting the chain.
## Impact
- **Confidentiality**: None
- **Integrity**: None
- **Availability**: High (Total network shutdown for a projected 15+ days)
## Remediation
### Patches
- The vulnerability was addressed in Acala Network PR [#2806](https://github.com/AcalaNetwork/Acala/pull/2806). The fix introduces a limit on the number of redeem requests processed in a single call to ensure the block remains within execution time limits.
### Workarounds
- No immediate non-code workarounds identified; requiring a chain upgrade/governance proposal to resume operations if the chain halts.
## Detection
- **Indicators of Compromise**: A sudden surge in small-value LDOT unbond requests from a high volume of unique or newly created addresses.
- **Detection Methods**: Monitoring the `RedeemRequests` map size and tracking the execution "weight" (time) of the `on_initialize` function in the Homa pallet.
## References
- **Vendor Fix**: [https://github.com/AcalaNetwork/Acala/pull/2806](https://github.com/AcalaNetwork/Acala/pull/2806)
- **Immunefi Writeup**: [https://immunefi.com/blog/acala-block-production-shutdown-bug-fix-review/](https://immunefi.com/blog/acala-block-production-shutdown-bug-fix-review/)
- **Whitehat Twitter**: [https://x.com/thel4stc0de](https://x.com/thel4stc0de)