Adapter Development

Build adapters to integrate new DeFi protocols with Gearbox Credit Accounts.

When to Build an Adapter

Build an adapter when you want to enable Credit Accounts to interact with a new DeFi protocol. Consider these options:

Approach
When to Use

Build an Adapter

The protocol is mature, has significant TVL, and you want it available across all Gearbox Credit Managers

Protocol Integration

You're building a protocol that wants to accept Credit Accounts as users (e.g., a DEX accepting leveraged trades)

Direct Contract

Your use case doesn't need leverage or margin trading features

Adapters make sense for:

  • DEX protocols (Uniswap, Curve, Balancer)

  • Yield vaults (Yearn, ERC-4626 vaults)

  • Liquid staking protocols (Lido, Rocket Pool)

  • Lending protocols (Aave, Compound)

Do not build adapters for:

  • Protocols with admin keys that can rug users

  • Protocols without audits or battle-testing

  • Highly experimental or unproven contracts

Architecture Overview

Adapters sit between Credit Accounts and external protocols:

The adapter's job is to:

  1. Accept calls from the CreditFacade (not users directly)

  2. Translate the call to the target protocol's interface

  3. Override recipient addresses to always be the Credit Account

  4. Manage token approvals safely

  5. Update token states (enable outputs, optionally disable inputs)

For architectural background, see Multicall System.

Building Your First Adapter

Step 1: Inherit AbstractAdapter

All adapters extend AbstractAdapter:

Example:

Step 2: Implement Core Functions

Add wrapper functions that call the target protocol:

Example:

Step 3: Implement Diff Functions

Diff functions calculate the input amount from the current balance:

Example:

Why diff functions exist:

When chaining operations, you often don't know exact amounts:

  • After a swap, you don't know exact output until execution

  • After partial withdrawals, remaining balance is variable

  • Diff functions say "use everything except X" instead of "use exactly Y"

Step 4: Add Security Modifiers

Every external function must use creditFacadeOnly:

Example:

Complete Example: ERC-4626 Vault Adapter

Here's a complete adapter for an ERC-4626 vault with all essential patterns:

Security Patterns Deep Dive

Why creditFacadeOnly Matters

Without this modifier, an attacker could call adapter functions directly:

Attack scenario without creditFacadeOnly:

  1. Attacker calls adapter.deposit(1000) directly

  2. Adapter tries to pull tokens from "current" Credit Account

  3. Without CreditFacade context, _creditAccount() returns address(0) or wrong account

  4. Tokens could be pulled from wrong account or transaction reverts unpredictably

With creditFacadeOnly:

  1. Only CreditFacade can call the adapter

  2. CreditFacade sets the active Credit Account before calling

  3. Adapter correctly identifies which account to operate on

  4. No unauthorized access possible

Recipient Override Pattern

Always hardcode the recipient as the Credit Account. Never accept user-specified recipients.

Attack scenario without recipient override:

Safe pattern:

Safe Approval Pattern

Approvals are reset to 1 (not 0) after each operation. This prevents:

  • Approval racing attacks

  • Gas waste from 0 -> N transitions

  • Front-running of approval transactions

Why reset to 1 instead of 0:

  • ERC-20 standard: 0 -> N costs more gas than 1 -> N

  • Prevents approval race conditions

  • Future operations don't need expensive zero-to-nonzero transition

Token State Management

Adapters automatically update which tokens are "enabled" on the Credit Account:

Testing with Foundry

Test adapters using Foundry fork tests:

Key test patterns:

  1. Fork testing - Test against real protocols on mainnet/testnet

  2. Access control - Verify creditFacadeOnly works

  3. Balance checks - Assert correct token transfers

  4. Diff functions - Verify correct amount calculation

  5. Edge cases - Test with zero amounts, max values, etc.

Deployment and Whitelisting

After writing and testing your adapter:

  1. Deploy the adapter - Deploy to mainnet with CreditManager and target addresses

  2. Submit governance proposal - Request adapter whitelisting via Gearbox governance

  3. Governance vote - DAO votes on adding adapter to Credit Manager(s)

  4. Adapter registration - If approved, adapter is added to allowedAdapters mapping

Governance process:

  • Submit proposal on Gearbox governance forum

  • Include audit report (required for new adapters)

  • Specify which Credit Manager(s) should whitelist it

  • DAO votes on proposal

  • If passed, adapter becomes available for Credit Accounts

Note: Each Credit Manager has its own adapter whitelist. An adapter approved for one Credit Manager isn't automatically available on others.

For architectural background, see Multicall System.

Best Practices

  1. Keep it simple - Adapters should be thin wrappers, not business logic

  2. No state - Adapters should be stateless (except immutables)

  3. Comprehensive diff - Implement diff functions for all variable-amount operations

  4. Always override recipients - Never let users specify where funds go

  5. Test thoroughly - Test both success and failure paths

  6. Document clearly - Write NatSpec comments explaining each function

  7. Declare adapter type - Set _gearboxAdapterType for proper categorization

Key Inherited Functions

AbstractAdapter provides these helper functions:

Function
Description

_creditAccount()

Returns current Credit Account address

_creditManager()

Returns Credit Manager address

_creditFacade()

Returns Credit Facade address

_getMaskOrRevert(token)

Gets token mask, reverts if not allowed

_execute(callData)

Executes call on target contract

_executeSwapSafeApprove(...)

Executes call with approval management

targetContract

Immutable address of wrapped protocol

Last updated