Full Report
Polkadot is a multi-chain env that uses a lot of crosschain communication. Each specialized blockchain is known as a parachain. Astar, the focus of this post, is a Polkadot parachain which supports both WASM and EVM support. Parachains like Astar are written in Rust with a framework called Substrate with many different modules to choose from. For EVM support, Frontier is used. Frontier allows for users to add in their own precompiled contracts as well. One of these is called assets-erc20, which allows to developers to deploy native assets. It adheres to the ERC20 standard where the address precompile has the top four bytes by 0xFFFFFFFF and the ID is the bottom part of the address. Slots in Ethereum are 32 bytes or 256 bits in size. The amount in the precompile contract, was set to be a u128. Why is this bad? Integer truncation is absolutely horrifying when handling assets like this. When calling transfer() on the precompiled contract, the integer would be truncated to 128 bits. So, if an attacker passed in type(uint128).max + 1 then the value being transferred would be zero. However, the smart contract assumed that the transfer succeeded, resulting in the contract having tracked this many! This allows for free transfers. This bug is awful. However, in practice, Uniswap and PancakeSwap pools were not vulnerable, since they do an actual balance check. They found a contract project called Kagla Finance that did not perform balance checks and assumed that the transfer worked. After successfully setting up a test environment, they used the bug to exploit the contract for 260K. Neat! This vulnerability existed in another Parachain as well but they couldn't find a good way to exploit it. This bug was very similar to the pwning.eth bug in Frontier in the past, which I was thinking about while reading it. So, how did this pop up again? The Frontier EVM has a fundamental flaw: Rust doesn't support u256 natively, forcing developers to truncate without special focus on this. Overall, a very interesting post on an integer overflow vulnerability. I didn't know much about Substrate based chains but this contains a good background as well.
Analysis Summary
# Vulnerability: Integer Truncation in Astar ERC20 Precompile Leading to Free Asset Transfers
## CVE Details
- CVE ID: Not explicitly provided in the text (This appears to be a recently discovered vulnerability reported via bug bounty, timeline suggests a pre-CVE assignment).
- CVSS Score: Not explicitly provided. Based on the impact (theft of significant funds), it would be **Critical**.
- CWE: CWE-195: External Control of Assumed-Immutable Positional Value (or similar to Integer Truncation/Boundary Errors).
## Affected Systems
- Products: Astar (Polkadot Parachain), Substrate-based chains utilizing the Frontier EVM compatibility layer with a vulnerable ERC20 precompile implementation.
- Versions: Versions incorporating the vulnerable implementation of the `assets-erc20` precompile before the fix referenced in PR #1081.
- Configurations: Any deployment using the specific `assets-erc20` precompile where the logic for handling $u256$ values from EVM calldata truncates them to $u128$ without explicit checks.
## Vulnerability Description
The vulnerability resides in the `assets-erc20` precompiled contract deployed on the Astar EVM, implemented via the Frontier compatibility layer. Ethereum slots are 32 bytes ($u256$). The amount parameter intended for token transfers in the precompiled contract was unexpectedly defined as a $u128$.
When an attacker calls the `transfer()` function, the 256-bit value being passed from the EVM calldata is truncated to 128 bits upon reading/storage within the Rust backend. If an attacker supplies a value greater than $u128.max$ (e.g., $type(uint128).max + 1$), the value truncates to zero ($0$) upon entering the $u128$ storage. Crucially, the contract logic *assumes* the transfer succeeded based on the input size, failing to verify the actual resulting amount or check the caller's balance against the *intended* (256-bit) amount. This leads to the contract incorrectly tracking that zero tokens were transferred, while the attacker's balance does not decrease, effectively allowing free issuance or transfer of tokens.
## Exploitation
- Status: **Exploited in the wild** (specifically against Kagla Finance). A Proof-of-Concept (PoC) was developed and used to drain funds.
- Complexity: **Low** (for vulnerable targets). Exploitation required submitting a specially crafted transaction to the vulnerable precompile.
- Attack Vector: **Network** (Remote via Ethereum RPC endpoint interaction).
## Impact
- Confidentiality: **No Impact** (Focus is on asset control).
- Integrity: **High**. Arbitrary tokens ($260K value stolen from Kagla Finance in the known exploit) can be transferred out of vulnerable contracts by inflating the attacker's balance without depleting the source contract's tracked balance.
- Availability: **Moderate/High** (Loss of liquidity/funds in vulnerable DeFi protocols).
## Remediation
### Patches
- A fix was implemented and merged via **AstarNetwork/Astar PR #1081**.
- The core fix involved modifying the `EvmDataReader::read()` function in Frontier to *always* include truncation checks when reading EVM calldata, preventing the fundamental issue of $u256$ truncation to Rust's native $u128$. Manual truncation checks were also added to the affected precompile logic.
### Workarounds
- Before patching, other protocols interacting with the precompile could mitigate risk by implementing strict **balance checks** before assuming a transfer operation within the precompile was successful (as Uniswap and PancakeSwap apparently did).
## Detection
- **Indicators of Compromise (IoCs):** Transactions directed to the Astar ERC20 precompile address ($0xFFFFFFFF...$) involving large amounts that subsequently result in contract balance discrepancies without corresponding reductions in the sender's internal tracking.
- **Detection Methods and Tools:** Monitoring Substrate/Frontier layer logs for transactions interacting with the ERC20 precompile where input data suggests a 256-bit value exceeding $u128.max$ was supplied. Auditing EVM smart contracts deployed on Substrate chains using Frontier for reliance on unverified results from native token precompiles.
## References
- Vendor Advisory/Fix: Astar Network PR #1081
- Vulnerability Report Source: hxxps://www.zellic.io/blog/finding-a-critical-vulnerability-in-astar