External contractor

This audit was performed by Carlos (Bloqarl) as an external contractor at Cyfrin, prior to or alongside founding Zealynx Security. It is not a Zealynx engagement, but is included here as part of Carlos’s professional security record.

D2 Finance · Smart Contract Security AssessmentD2 Finance Client Hub

D2 Finance Vault and Strategy (v2.1)

Cyfrin engagement on D2 Finance, a multi-chain ETF-style vault protocol deployed across Berachain, Arbitrum, Base, and Ethereum. The audit ran from January 10 to February 14, 2025, combining manual review with stateful fuzzing across the vault, strategy, and 12 integration modules covering Aave, Camelot, Dolomite, GMX V2, 1inch, Kodiak, Pendle, Silo, Trader Joe and WETH. The review surfaced 24 findings (2 critical, 2 high, 7 medium, 7 low, 6 informational), including a broken GMX V2 withdrawal path that would have permanently locked user funds, a private key checked into the makefile, an ERC-4626 share-pricing mismatch on cross-chain transfers, and a Berachain reward-claiming interface bug. D2 resolved 19 findings and acknowledged 5. Carlos contributed to this engagement as external contractor at Cyfrin; the testimonial from Dacian on the Zealynx site references this collaboration.

BerachainArbitrumBaseEthereumSoliditySmart Contract Code Review2025-02-24d2-contractsZealynx methodology
Total findings
24
19 fixed · 5 acknowledged
Critical
02
High
02
Medium
07
Low + Info
13
02

Scope

16 files
Repository
Initial commit
c2fc257605eb
Platform
Berachain · Arbitrum · Base · Ethereum · Solidity
Methodology
File
contracts/D2OFT.sol
contracts/Strategy.sol
contracts/VaultV0.sol
contracts/VaultV3.sol
contracts/modules/Aave.sol
contracts/modules/Bera.sol
contracts/modules/Camelot.sol
contracts/modules/D2.sol
contracts/modules/Dolomite.sol
contracts/modules/GMXV2.sol
contracts/modules/IDolomite.sol
contracts/modules/Inch.sol
contracts/modules/Pendle.sol
contracts/modules/Silo.sol
contracts/modules/Trader.sol
contracts/modules/WETH.sol
03

Findings

click any row for the full write-up
Severity
ID
Finding
Status
criticalF-2025-0001GMXV2_Module withdrawal functionality is broken due to missing callback implementationFixedcriticalF-2025-0002PRIVATE_KEY exposed in makefile and other sensitive data committed to the repositoryFixedhighF-2025-0003Users may lose value when transferring ERC-4626 vault shares cross-chainFixedhighF-2025-0004Reward claiming fails for Berachain RewardVaults due to incorrect interfaceFixedmediumF-2025-0005Lack of slippage protection allows exploitation of Pendle tradesFixedmediumF-2025-0006Unsafe token transfers in VaultV3 can lead to state inconsistenciesFixedmediumF-2025-0007Incorrect chainid prevents correct Strategy deployment on BerachainFixedmediumF-2025-0008Incorrect interface for ExchangeRouter::updateOrder prevents order updates in GMX V2FixedmediumF-2025-0009Bera_Module fails to stake in BGTStaker due to missing Boost integrationFixedmediumF-2025-0010Bera_Module::bera_kodiakv3_swap broken due to deadline parameter mismatchFixedmediumF-2025-0011Kodiak swap functions do not check if output token is approved, risking stuck assetsFixedlowF-2025-0012Aave module lacks reward-claiming functionalityFixedlowF-2025-0013Compromised trader account can block admin from revoking accessFixedlowF-2025-0014Improper deadline handling across Bera_Module DEX operationsAcklowF-2025-0015Missing events for important state changesAcklowF-2025-0016Silo_Module::silo_execute will revert as approval is to the wrong contractFixedlowF-2025-0017Silo and Dolomite lack LTV limit, increasing liquidation riskAcklowF-2025-0018Borrowing non-approved tokens can bypass trading restrictionsAckinfoF-2025-0019ETH calls on Dolomite_Module have no corresponding calls on DolomiteFixedinfoF-2025-0020Unnecessary validation in Bera_Module::bera_infrared_stake should follow standard patternFixedinfoF-2025-0021Unused imports across multiple modulesFixedinfoF-2025-0022Aave swapBorrowRateMode is deprecatedFixedinfoF-2025-0023Selectors for Bera_Module::bera_kodiakv2_swap and bera_kodiakv3_swap need to be separately addedFixedinfoF-2025-0024Consider using Ownable2Step instead of OwnableAck
04

Key Findings

  • GMX V2 withdrawal path was non-functional. The strategy registered for the afterWithdrawalCancellation callback but never implemented the corresponding interface function. A user-initiated withdrawal would have completed at GMX side, fired the callback into the strategy, and reverted, permanently locking GM token shares and the assets backing them.
  • Private key was checked into the makefile. The repository shipped with a hardcoded PRIVATE_KEY (and other secrets) inside the build script, exposing any address derived from that key to anyone with read access to the repo. All affected accounts had to be rotated.
  • Cross-chain ERC-4626 share transfers leaked value. When a user bridged vault shares through D2OFT to a chain where the vault price-per-share had moved, share burning and minting used the source-chain ratio, causing the receiver to gain or lose value depending on which side had appreciated.
  • Berachain reward claiming used the wrong interface. Bera_Module claimed rewards from Berachain RewardVaults using an interface that did not match the deployed contract, so reward harvesting always reverted on Berachain.
  • Slippage protection was hardcoded to zero across the Pendle integration. Six entry points in Pendle_Module (deposit, withdraw, swap, claim, exit) passed minAmountOut = 0, leaving every Pendle trade fully exposed to MEV sandwiching and price manipulation.
  • VaultV3 did not validate token transfer success. custodyFunds() and returnFunds() updated custodied state and emitted events regardless of whether the underlying ERC-20 transfer succeeded, opening multiple paths to vault state desynchronisation under USDC pause, blacklisting, or false-return tokens.
  • Wrong Berachain chain ID hardcoded. Strategy::constructor checked block.chainid == 80000 for Berachain instead of the correct 80094, meaning the Berachain branch never initialised facets and the strategy was effectively undeployable on Berachain until redeployed.
05

Team & approval

Auditor
Carlos (Bloqarl)
@TheBlockChainer
06

Disclaimer

This audit is not an endorsement and does not constitute investment advice. Zealynx reviewed the codebase at the commits listed in section 02 over the engagement window. Findings are limited to issues identified within that scope and do not preclude the existence of other vulnerabilities. Subsequent code changes are not covered by this report unless the engagement is explicitly extended.

Download PDF (29p)
ZEALYNX SECURITY · published 2025-02-24
24 findings · Solidity