All audits
FailedArbitrumIndependent

Radiant Multisig Compromise (2024)

Smart contract security audit by TierZero · 2024-10-15

Independent research. This is an unsolicited security analysis published by TierZero — not a commissioned audit, and no certificate is issued. It reflects our own review of public code and on-chain events.

Findings summary

1
Critical
2
High
2
Medium
1
Low
1
Informational

Independent research — not a commissioned audit. This is a post-mortem analysis of a publicly disclosed incident, compiled from public reporting for educational purposes.

What the protocol did

Radiant Capital ran an Aave v2-derived cross-chain money market, live on Arbitrum and BNB Chain, with LayerZero wiring the two deployments together so collateral on one chain could back borrows on the other. Like most Aave forks, the lending pools sat behind upgradeable proxies, and the authority to point those proxies at new implementation logic — plus other privileged configuration — was held by a Gnosis Safe (Safe{Wallet}) multisig, reported at a 3-of-11 threshold. That multisig was the single most powerful key in the system: whoever controlled enough signatures controlled the pools.

In October 2024, attackers reached that threshold without compromising any Solidity code. They compromised the humans.

The vulnerability

This wasn't a reentrancy bug or a rounding error. The bug class is blind co-signing on a privileged, un-timelocked upgrade path — signers approving execTransaction payloads they could not independently verify, against contracts where a single approved transaction could redirect core protocol logic.

Two things had to both be true for this to be catastrophic:

  1. The multisig's admin surface was large and immediate — no timelock separated "signers approve" from "logic changes in production."
  2. Signers verified transactions using the same compromised endpoint that displayed them, so there was no independent channel to catch a mismatch between intended and actual calldata.

Illustrative pattern of the exposed surface:

// PoolAddressesProvider-style contract, owned by the multisig
contract PoolAddressesProvider is Ownable {
    address public poolImpl;

    function setPoolImpl(address newImpl) external onlyOwner {
        poolImpl = newImpl;   // takes effect immediately, no delay,
    }                         // no independent verification step
}

onlyOwner is correctly enforced at the contract level — that was never the weakness. The weakness is architectural: one execTransaction reaching signature threshold is sufficient to rewrite pool logic, and nothing in the stack forces a second, out-of-band confirmation that what signers saw is what they signed.

How the exploit worked

  1. Social engineering. Attackers posed as a contractor on Telegram and sent Radiant developers a file disguised as a project deliverable, which dropped malware on their machines.
  2. Endpoint compromise. The malware sat on enough individual signer devices to matter, reportedly manipulating the Safe transaction-signing flow itself.
  3. Calldata spoofing. When signers went to approve routine transactions, the malware substituted malicious calldata while the Safe UI kept displaying what looked like a benign, expected transaction — the classic blind-signing failure mode.
  4. Threshold reached. Enough spoofed approvals accumulated to clear the multisig threshold, and the malicious execTransaction executed on-chain exactly as crafted by the attacker, not as displayed to the signers.
  5. Ownership/implementation redirected. The transaction altered control of the lending pool contracts on Arbitrum and BNB Chain, pointing them at attacker-controlled logic.
  6. Drain. The malicious logic swept user funds, leveraging the standing token approvals users had already granted to the lending pools. Publicly reported losses were on the order of $50 million across both chains, drained within a short window before Radiant could pause the markets.

How an audit catches this

A code-only review of the pool contracts would have found the onlyOwner gate working exactly as designed — which is precisely why this class of finding gets missed. What a thorough engagement checks instead:

  • Enumerate every privileged, state-changing entry point (upgrade, setImplementation, transferOwnership, pause/unpause) and flag any that take effect with zero delay after multisig approval.
  • Require a timelock on upgrade and implementation-change paths, sized so the community and monitoring infra can react before a malicious change lands — this is the single highest-leverage mitigation for exactly this incident class.
  • Test the "N signers compromised" scenario as an explicit invariant, not an assumption: if threshold-many devices are malware'd, what is the blast radius, and is there any control besides trusting the endpoints?
  • Push for calldata verification independent of the signing device — transaction simulation (e.g., Tenderly) plus a second, out-of-band published hash of the pending transaction that signers reconcile against before approving.
  • Flag standing token approvals as an amplifier: if pool contracts hold transferFrom rights over large aggregate balances, a compromised implementation turns every prior approval into an attacker's withdrawal function. This same approval-abuse pattern shows up in EVM front-running and approval-drain schemes discussed in our piece on Permit2 gasless approvals and their sniping-bot exposure.

This is a review category we run explicitly in every smart contract audit engagement: admin-key and upgrade-path mapping isn't optional scope, it's usually where the largest single-transaction loss is hiding, upgradeable-authority centralization is a recurring theme across chains — we cover the analogous failure mode for program upgrade authorities in our analysis of upgradeable Solana programs and BPF loader risk.

Remediation

Radiant's own response — pausing markets, working with exchanges to freeze traceable funds, and overhauling signing procedures — is public record and outside our scope to relitigate. The structural fixes that generalize to any protocol running an owner-upgradeable proxy behind a multisig:

  • Put a real timelock between multisig approval and effective execution of upgrade or ownership-change transactions.
  • Separate emergency pause authority (fast, narrow) from upgrade authority (slow, timelocked, broad) — they should not share a signer set or a threshold.
  • Mandate hardware-wallet clear-signing or independent transaction simulation for every signer before approval; never trust a single device's rendering of calldata.
  • Cap or expire standing approvals into pool contracts where practical, so a compromised implementation has a smaller pool of funds to reach.
  • Treat signer endpoint security (device hygiene, phishing resistance, isolated signing hardware) as part of the protocol's security boundary, not an out-of-band IT concern — it's the same boundary secure smart contract development practices assume is solid when they hand upgrade rights to a multisig.

If your protocol has an owner- or multisig-controlled upgrade path, get the admin surface mapped and the timelock question answered before it becomes a post-mortem — talk to us about a smart contract audit.

Need your contracts audited?

Manual review + tooling across TON, Solana and EVM — certificate and full report included.

Get an audit