Context
On August 19, 2026, the well-known cross-chain bridge project Allbridge was attacked, resulting in a loss of approximately $190,000. However, this attack spanned nearly a month to complete. Below is a detailed analysis by the SlowMist Security Team regarding this incident:
Prerequisites
To understand this attack, we first need to understand Circle’s CCTP protocol and its cross-chain messaging system.
CCTP is Circle’s cross-chain transfer protocol. It works by burning USDC on the source chain and minting an equivalent amount of USDC on the target chain, preventing bridge contracts from artificially inflating balances.
A normal CCTP transfer typically follows these steps:
Source chain TokenMessenger burns USDC
-> Authenticate and forward messages via Circle MessageTransmitter
-> Target chain Circle TokenMessenger receives message
After verification by TokenMessenger, USDC is minted.
-> Wait until the Router sees the actual receipt before transferring USDC to the user.
Circle's MessageTransmitterV2 is the contract responsible for transmitting messages. It issues an attestation for the complete message, which is Circle's signed verification of the specified cross-chain message. However, this attestation only confirms that the message content has been authenticated by Circle; it does not, by itself, verify that the amount stated in the message has actually been transferred.
The Circle TokenMessengerV2 on the destination chain is responsible for minting. After receiving the message, MessageTransmitterV2 locates the contract to callback based on the recipient address in the message header. A standard CCTP message sets this address to the destination chain’s TokenMessengerV2 contract. It then verifies the source TokenMessenger, token, amount, and recipient address; only after all checks pass is USDC minted.
Allbridge’s CCTP module comes later in this process. It aggregates completed deposits into records that the Router can recognize, and the Router then transfers the tokens to the user. Here is a critical point to note: an attestation being valid does not mean that token burning actually occurred on the source chain, does not mean that token minting has been executed on the destination chain, and does not mean that the Router has genuinely received the corresponding USDC. At this point, we can understand that Circle’s sendMessage is a generic interface. Anyone can call it, input cross-chain message content, and have Circle authenticate that content. Calling this interface itself does not automatically burn USDC or automatically mint USDC. A normal CCTP transfer still requires participation from the TokenMessenger on the source chain, which first burns the USDC and then generates a message containing the burn information. In this attack, however, the attacker constructed only the cross-chain message, bypassing the step of burning USDC.
Root cause
In Allbridge's CCTPTokenMessenger contract, the receiveCctpMessage function, which receives cross-chain messages, lacks checks to verify whether the sender field in the CCTP message header matches the remote TokenMessenger, and does not verify whether the recipient field equals Circle's TokenMessengerV2 contract. As a result, MessageTransmitterV2.receiveMessage passes the forwarded cross-chain message to an attacker-controlled contract to determine whether token minting was successful. Since this contract does not re-verify whether the Router's USDC balance has genuinely increased before accounting, it blindly trusts the amount specified in the attacker-crafted message and records it as available balance (the receivedTokenAmount corresponding to the messageHash in the hookData of the cross-chain message).
No checks or protections were provided in hookData. When executing the payment, the Router recalculates the messageHash based on the call parameters and then queries the previously recorded internal deposit balance for that hash. However, an attacker can offline compute the corresponding hash for the same set of parameters before sending a message on Polygon, and directly insert this precomputed messageHash into the cross-chain message’s hookData. This causes the system to match the attacker’s own fabricated internal record, unrelated to actual asset settlement.
Therefore, attackers can directly call MessageTransmitterV2.sendMessage on Polygon to construct arbitrary cross-chain messages, wait for Circle to sign them, and cause the attestation verification on the Base chain to succeed, treating the forged message as a legitimate cross-chain receipt, ultimately triggering the Router to transfer tokens.
Attack Step Analysis
1. On July 26, 2026, the attacker first directly called the sendMessage function of the Circle MessageTransmitterV2 contract on Polygon. This was a general cross-chain message transmission operation that generated a MessageSent event, but no USDC burn occurred. Circle subsequently issued an attestation for the complete message, which was executed as intended by the protocol.

The message was populated with CCTP-style data. The source domain is Polygon, the target domain is Base, the claimed amount is 1,000,000 USDC, feeExecuted is zero, and destinationCaller points to Allbridge’s CCTPTokenMessenger contract. The attacker set the message header recipient to their own contract, set the sourceSender in the message body to the remote Messenger address configured in the settings, and inserted the precomputed Router messageHash into hookData for later verification.
2. After the malicious cross-chain message was created, the attacker waited approximately 24 days. Since the Base Router is a forwarding router, it typically does not hold large liquidity for extended periods. On August 19, 2026, the Allbridge relayer minted USDC onto the Router via a genuine CCTP deposit from another user, amounting to approximately 191,112 USDC, bringing the Router’s balance to about 191,156 USDC.
This balance consists of cross-chain funds awaiting transfer to real users. The attacker exploited this brief waiting period, initiating the official attack transaction six seconds after the legitimate deposit occurred.

3. The attack contract first calls the receiveCctpMessage function of the CCTPTokenMessenger contract, passing in the message and signature data (attestation) obtained from the Polygon transaction, where both the destinationCaller check and sourceSender check are bypassed (both constructed by the attacker). It then calls the receiveMessage function of the Circle MessageTransmitterV2 contract, which, based on the recipient in the message header, callbacks the attack contract. The attack contract immediately returns success without executing the expected token minting operation in the Circle TokenMessenger contract. Furthermore, Allbridge does not re-verify the Router’s balance nor check whether the callback target contract equals the Circle TokenMessengerV2; instead, it directly writes amount - feeExecuted into receivedMessages[messageHash], generating an internal credit of 1,000,000 USDC.

4. Since the target amount constructed in the attacker’s previously created cross-chain message was 1,000,000 USDC, and Router had only approximately 191,156 USDC at the time, the attacker first provided 808,844 USDC to Router via an Aave flash loan, temporarily bringing the balance to the amount claimed in the fraudulent message, thereby enabling the subsequent token transfer.

5. The attacker then calls the Router’s receiveToken function to process the receipt and settlement. The Router recalculates the hash based on the call parameters, obtaining a value identical to the messageHash previously computed and fabricated by the attacker in hookData. It then merely checks whether the receivedTokenAmount record corresponding to that messageHash in the CCTPTokenMessenger contract is greater than zero, and if so, considers the genuine deposit tokens to have been received. Since the Router charges a 0.1% fee, it immediately transfers the remaining 999,000 USDC to the attacker’s contract after deducting the fee.
Throughout the process, the Router only checks whether the credit exists in the CCTPTokenMessenger contract, without re-verifying whether this credit corresponds to an actual on-chain asset transfer of equal value.


6. After stealing 999,000 USDC, the attacker repaid 808,844 USDC in principal and approximately 404.422012 USDC in flash loan fees to Aave, leaving approximately 189,751.554381 USDC as profit. This transaction nearly emptied Router’s 191,156 USDC. The majority of the loss came from real cross-chain deposits that had just arrived but had not yet been transferred to users.
Interestingly, the 1,000 USDC fee collected by Router was later stolen by other attackers using the same attack method.
Summary
The core issue in this attack was Allbridge’s lack of validation for the validity of cross-chain messages. Circle’s attestation can only verify that the message content has not been tampered with, but it cannot prove that the cross-chain message genuinely triggered a token burn or mint operation. Allbridge directly trusted the amount, source address, and messageHash self-constructed by the attacker within the CCTPTokenMessenger message, recorded them as redeemable balances, and treated them as legitimate deposits.
The SlowMist Security Team recommends that project teams uphold three boundaries when addressing the issue:
1. The sender parameter in the message header must correspond to a trusted source component contract;
2. The recipient parameter in the message header must be restricted to the target chain’s Circle TokenMessengerV2 contract;
3. A redeemable deposit record can only be created after the Router's USDC balance has been genuinely minted and increased.
For a cross-chain bridge system, the most important thing is that properly authenticated messages are a necessary condition for cross-chain settlement, and the actual arrival of assets is the basis for Router’s final payment.

