
Garden Finance Competitive Audit: Code4rena
Technical
TL;DR, Code4rena conducted a competitive audit of Garden's cross chain HTLC contracts across EVM, Solana, Starknet, and Move in December 2025. 813 independent security researchers submitted findings. One Medium severity vulnerability was identified, an unchecked approve() return in UDA.sol; and resolved using SafeERC20. No High or Critical issues were found.
Garden ran a competitive security audit through Code4rena, covering the broadest scope of any Garden security review to date; 15 smart contracts written across four languages and four chains. Unlike a traditional firm engagement, Code4rena's format opens the codebase to a large pool of independent security researchers who submit findings competitively, with rewards paid out based on severity and validity. 813 submissions were received over a two-week period, with $37,500 in total rewards.
The audit specifically targeted Garden's HTLC based atomic swap architecture across Bitcoin, EVM, Solana, Sui, and Starknet the full set of chains Garden supported at the time. The codebase under review comprised 2,163 lines across Cairo, Move, Rust, and Solidity.
Scope
The audit ran from November 24 to December 8, 2025, assessed against the C4 Garden Finance repository at commit cf7c5b09b7156d6806cc1e68dd924c1b01a5236d and the report was published on 12th February 2026. Fifteen smart contracts were in scope across four languages and platforms:
- Solidity / EVM: including UDA.sol, NativeHTLC.sol, ArbNativeHTLC.sol, and related EVM swap contracts
- Rust / Solana: solana-native-swaps and solana-spl-swaps programs implementing native SOL and SPL token HTLC swaps
- Cairo / Starknet: htlc.cairo implementing HTLC logic on Starknet
- Move / Sui: Move-based HTLC modules
The assessment goals framed by Garden covered state transition correctness, transfer integrity, order uniqueness, and refund authenticity, consistent with the security questions applied in the Zellic Move audit now extended across all supported chains simultaneously.
Findings
The audit produced one unique vulnerability. Zero High severity issues were identified.
M-01; Unchecked approve() return causes permanent fund loss in UDA.sol | Medium
The UniqueDepositAddress.initialize() function calls ERC20.approve() without checking its return value:
HTLC(_addressHTLC).token().approve(_addressHTLC, amount);Non-standard ERC20 tokens, including USDT and BNB, return false on failed approvals rather than reverting. Because the return value is ignored, execution continues even when approval fails. The result: the contract marks itself as initialized, the token allowance remains at zero, and initiateOnBehalf() executes but the HTLC cannot transfer tokens. The deposited funds become permanently locked with no recovery path, since initialized prevents re-initialization.
The contract already imports SafeERC20 and uses it in the recover() functions — the fix was to apply it consistently to the approve() call as well.
This finding was independently identified and submitted by ten separate researchers.
Missing redeemer != refundee validation enables same-party orders and instant self-refunds | Low
The initiate instruction in both Solana HTLC implementations solana-native-swaps and solana-spl-swaps, does not enforce that the redeemer and refundee are different addresses. When both are set to the same address, instant_refund can be called immediately without revealing the secret or waiting for timelock expiry, since the redeemer's consent is the only requirement for instant refund and the same address controls both roles. This breaks the fundamental HTLC invariant: the counterparty redeems with the secret, and only the initiator can refund after expiry.
Project-wide spelling and identifier typos | Informational
Spelling errors were identified across EVM, Cairo, and Starknet codebases. The most significant from an integration standpoint: the custom error identifiers NativeHTLC__IncorrectFundsRecieved and ArbNativeHTLC__IncorrectFundsRecieved in the Solidity contracts contain a misspelling of "Received." Because custom error selectors are derived from keccak256(ErrorSignature), renaming changes the on-chain selector, any external tooling or decoders referencing the old selector will break on update. Additional typos were found in Cairo variable names (intiate instead of initiate) and across the Starknet test suite (INTIATE_TYPE instead of INITIATE_TYPE).
Action
The Medium finding in UDA.sol was resolved by replacing the unchecked approve() call with safeApprove() from the SafeERC20 library already imported in the contract, bringing the initialize() function in line with the recover() functions that already used SafeERC20 correctly.
The Low finding in the Solana programs was addressed by adding a require!(redeemer != refundee) check in both initiate functions across solana-native-swaps and solana-spl-swaps.
The identifier typos were corrected across EVM, Cairo, and Starknet codebases, error names updated to use the correct "Received" spelling, Cairo variable names corrected to initiate, and the Starknet test suite updated to INITIATE_TYPE throughout.
Summary
813 independent researchers. 15 contracts across four languages and four chains. One Medium finding, zero High or Critical issues. Medium was resolved using a library already present in the codebase. The Low and Informational findings were also addressed.
The Code4rena audit was the fourth and broadest security review in Garden's programme, following assessments by OtterSec (August 2023), Trail of Bits (April 2024), and Zellic (June 2025).
Last updated