Gyro Finance GYD CCIP Escrow Approval Exploit

On Ethereum mainnet, Gyro Finance’s GYD bridge escrow was exploited on January 30, 2026. The attacker used a crafted CCIP message to make the escrow contract approve unlimited GYD allowance, then drained the escrow via transferFrom.

The attack vector is an arbitrary external call / access control bypass inside the CCIP receive handler. The exploit abuses unvalidated recipient and data fields in _ccipReceive, allowing the attacker to turn a CCIP message into an arbitrary call executed by the escrow.

The vulnerable contract is the GYD L1 CCIP Escrow proxy at 0xa1886c8d748deb3774225593a70c79454b1da8a6, which points to implementation 0x79ec4a4440878b25b0cbd902fb3414015c28bbc5 via the EIP-1967 implementation slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc. The vulnerable function is GydL1CCIPEscrow._ccipReceive(Client.Any2EVMMessage).

The flaw is that _ccipReceive decodes recipient, amount, and data from the CCIP message and then calls recipient.functionCall(data) without validating the recipient or restricting callable targets. In GydL1CCIPEscrow.sol lines 210-235, the contract transfers GYD to recipient and then executes arbitrary calldata on recipient if data.length > 0, enabling a call such as approve(attacker, max) against the GYD token contract. This trusts external CCIP message payloads beyond sender validation and lets the escrow execute unbounded external calls with its own authority.

Decoded CCIP message (tx 0x45739a92c2d99f172a74d8028736a2fd1b507ac6fc134680cd1dccd3c572c600, selector 0x85572ffb) shows the attacker payload explicitly: messageId=0xe5568505d3e5c82ce6194ee92a289f5a48693f23135bf2caad9ec934da863ce9, sourceChainSelector=4949039107694359620 (Arbitrum selector referenced in the escrow code), sender=0xca5d8f8a8d49439357d3cf46ca2e720702f132b8, recipient=0xe07f9d810a48ab5c3c914ba3ca53af14e4491e8a (GYD), amount=1, and data=0x095ea7b3... (ERC20 approve(attacker, 2^256-1)). This message carries no destTokenAmounts, yet the escrow still performs the transfer and the arbitrary call based solely on any2EvmMessage.data.

Call flow (tx 0x45739a92c2d99f172a74d8028736a2fd1b507ac6fc134680cd1dccd3c572c600, 2026-01-30T20:27:59Z): attacker -> EVM2EVMOffRamp (0xb1dc65a4) -> CCIPRouter (0x3cf97983) -> GydL1CCIPEscrow.ccipReceive (0x85572ffb) -> GYD.transfer (0xa9059cbb) -> GYD.approve (0x095ea7b3).

On-chain evidence in tx1 shows the escrow approved the attacker for max allowance: the Approval log (topic 0x8c5be1e5..., logIndex 0x11c) is emitted by 0xe07f9d810a48ab5c3c914ba3ca53af14e4491e8a (GYD) with owner=0xa1886c8d748deb3774225593a70c79454b1da8a6, spender=0x7dd4075a6eae9f18309f112364f0394c2dfa8102, and amount 0xffff...ffff. The Transfer log (topic 0xddf252ad..., logIndex 0x11b) shows amount=1 moved from the escrow to the GYD token contract, consistent with recipient=GYD in the decoded payload. The escrow’s GYDClaimed event (topic 0x022f3901..., logIndex 0x11d) records chainSelector=0x44ae84d8e9a37444, recipient=GYD, amount=1, and total=6099337379423890415819985, confirming the message’s minimal withdrawal and that accounting was reduced by only 1 wei of GYD.

The drain happened in tx 0xe03ac744df1910a71fedab58bc6a32ab5afe1cb4fcad94a0e5c8d7edf0d7405c (2026-01-30T20:40:59Z). The attacker called GYD.transferFrom(0xa1886c8d748deb3774225593a70c79454b1da8a6, 0x7dd4075a6eae9f18309f112364f0394c2dfa8102, 6099337379423890415819985) (0x23b872dd...), and the Transfer log (topic 0xddf252ad..., logIndex 0x225) shows 6,099,337.379423890415819985 GYD moved from the escrow to the attacker.

Balance/allowance deltas show the exploit mechanics precisely. Before tx1, the escrow held 6,099,337.379423890415819986 GYD and the attacker held 0. After tx1, the escrow balance decreased by 1 and the allowance from escrow to attacker became 2^256-1. After tx2, the escrow balance was 0 and the attacker balance was 6,099,337.379423890415819985 GYD.

Financial impact on-chain is the loss of 6,099,337.379423890415819985 GYD from the L1 escrow. Public estimates peg the attacker’s realized proceeds at 300.2 ETH ($696k), which are not directly reflected in the two transactions above and likely resulted from subsequent swaps. The loss is borne by the protocol’s bridge escrow (and therefore by GYD holders relying on L1 backing), leaving the escrow under-collateralized by the drained amount.

Related URLs: https://etherscan.io/tx/0x45739a92c2d99f172a74d8028736a2fd1b507ac6fc134680cd1dccd3c572c600 https://etherscan.io/tx/0xe03ac744df1910a71fedab58bc6a32ab5afe1cb4fcad94a0e5c8d7edf0d7405c