Compressors
Compressor contracts aggregate on-chain data efficiently. Instead of dozens of individual reads, a single compressor call returns complete protocol state.
Discovering Compressor Addresses
Use AddressProvider to find compressor addresses:
Solidity Usage
Solidity
[address compressor] = addressProvider.getLatestAddressByContractType( AP_MARKET_COMPRESSOR, VERSION_RANGE_310 );
TypeScript Usage
TypeScript
import { AP_MARKET_COMPRESSOR, VERSION_RANGE_310 } from '@gearbox-protocol/sdk'; const [compressor] = sdk.addressProvider.mustGetLatest( AP_MARKET_COMPRESSOR, VERSION_RANGE_310 );
MarketCompressor
The primary data aggregation contract. Returns complete market state including pools, credit managers, and price oracles.
Interface
Solidity
interface IMarketCompressor { function getMarkets(MarketFilter memory filter) external view returns (MarketData[] memory); function getMarketData(address pool) external view returns (MarketData memory); function getPoolState(address pool) external view returns (PoolState memory); }
MarketFilter
Solidity
struct MarketFilter { address[] configurators; // Filter by Risk Curator addresses address[] pools; // Filter by specific pool addresses address underlying; // Filter by underlying token (e.g., USDC) }
Pass empty arrays and address(0) for no filtering.
Solidity Usage
Solidity
import {IMarketCompressor} from "@gearbox-protocol/periphery-v3/contracts/interfaces/IMarketCompressor.sol"; import {MarketData, MarketFilter} from "@gearbox-protocol/periphery-v3/contracts/types/MarketData.sol"; IMarketCompressor compressor = IMarketCompressor(MARKET_COMPRESSOR_ADDRESS); // Get single market MarketData memory data = compressor.getMarketData(poolAddress); // Get all USDC markets MarketFilter memory filter = MarketFilter({ underlying: USDC, configurators: new address[](0), pools: new address[](0) }); MarketData[] memory usdcMarkets = compressor.getMarkets(filter);
TypeScript Usage
TypeScript
import { marketCompressorAbi } from '@gearbox-protocol/sdk'; // Get all markets const markets = await client.readContract({ address: compressorAddress, abi: marketCompressorAbi, functionName: 'getMarkets', args: [{ configurators: [], pools: [], underlying: '0x0000000000000000000000000000000000000000' }], }); // Get specific pool data const marketData = await client.readContract({ address: compressorAddress, abi: marketCompressorAbi, functionName: 'getMarketData', args: [poolAddress], });
MarketData Structure
Solidity
struct MarketData { PoolState pool; // Pool state and rates QuotaKeeperState quotaKeeper; // Quota limits and rates CreditSuiteData[] creditManagers; // All CMs for this market PriceOracleState priceOracle; // Oracle configuration TokenData[] tokens; // Allowed collateral tokens }
Key fields in PoolState:
| Field | Type | Description |
|---|---|---|
baseParams.addr | address | Pool contract address |
availableLiquidity | uint256 | Borrowable liquidity |
dieselRate | uint256 | Share price (RAY) |
supplyRate | uint256 | Lender APY (RAY) |
baseInterestRate | uint256 | Borrower APR (RAY) |
totalAssets | uint256 | Total pool value |
Key fields in CreditSuiteData:
| Field | Type | Description |
|---|---|---|
creditManager | address | Credit Manager address |
creditFacade | address | Credit Facade address |
creditConfigurator | address | Configurator address |
debtLimits | DebtLimits | min/max debt per account |
collateralTokens | CollateralToken[] | Allowed tokens + LTs |
CreditAccountCompressor
Fetches credit account data with filtering and pagination.
Interface
Solidity
interface ICreditAccountCompressor { function getCreditAccounts( address creditManager, CreditAccountFilter memory filter, uint256 offset ) external view returns (CreditAccountData[] memory accounts, uint256 total); function countCreditAccounts( address creditManager, CreditAccountFilter memory filter ) external view returns (uint256); function getCreditAccountData( address creditManager, address creditAccount ) external view returns (CreditAccountData memory); }
CreditAccountFilter
Solidity
struct CreditAccountFilter { address owner; // Filter by owner (address(0) = any) uint256 minHealthFactor; // Minimum HF (0 = no min) uint256 maxHealthFactor; // Maximum HF (type(uint256).max = no max) bool includeZeroDebt; // Include accounts with no debt bool reverting; // Include reverting accounts }
Solidity Usage
Solidity
import {ICreditAccountCompressor} from "@gearbox-protocol/periphery-v3/contracts/interfaces/ICreditAccountCompressor.sol"; ICreditAccountCompressor compressor = ICreditAccountCompressor(compressorAddress); // Get accounts with low health factor (for liquidation) CreditAccountFilter memory filter = CreditAccountFilter({ owner: address(0), minHealthFactor: 0, maxHealthFactor: 10000, // HF < 1.0 includeZeroDebt: false, reverting: false }); (CreditAccountData[] memory accounts, uint256 total) = compressor.getCreditAccounts(creditManager, filter, 0);
TypeScript Usage
TypeScript
import { creditAccountCompressorAbi } from '@gearbox-protocol/sdk'; // Get all accounts with debt const [accounts, total] = await client.readContract({ address: compressorAddress, abi: creditAccountCompressorAbi, functionName: 'getCreditAccounts', args: [ creditManagerAddress, { owner: '0x0000000000000000000000000000000000000000', minHealthFactor: 0n, maxHealthFactor: BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'), includeZeroDebt: false, reverting: false, }, 0n, // offset ], }); console.log(`Found ${total} accounts, fetched ${accounts.length}`);
CreditAccountData Structure
Solidity
struct CreditAccountData { address addr; // Credit Account address address owner; // Account owner address creditManager; // Parent Credit Manager uint256 debt; // Total debt (principal + interest) uint256 cumulativeIndexLastUpdate; uint256 cumulativeQuotaInterest; uint128 quotaFees; uint256 enabledTokensMask; // Bitmask of enabled tokens uint256 healthFactor; // Current HF (10000 = 1.0) TokenInfo[] tokens; // Token balances and values bool isLiquidatable; }
Pagination
Large result sets are paginated. Use offset to fetch subsequent pages:
TypeScript
const PAGE_SIZE = 100n; let offset = 0n; let allAccounts: CreditAccountData[] = []; while (true) { const [accounts, total] = await compressor.read.getCreditAccounts([ creditManager, filter, offset, ]); allAccounts.push(...accounts); offset += BigInt(accounts.length); if (offset >= total) break; }
PriceFeedCompressor
Aggregates price feed state for oracle updates.
Interface
Solidity
interface IPriceFeedCompressor { function getUpdatablePriceFeeds(address priceOracle) external view returns (PriceFeedData[] memory); function loadPriceFeedTree(address priceOracle, address token) external view returns (PriceFeedTreeNode memory); }
TypeScript Usage
TypeScript
// Get all feeds that need updating const feeds = await client.readContract({ address: priceFeedCompressor, abi: priceFeedCompressorAbi, functionName: 'getUpdatablePriceFeeds', args: [priceOracleAddress], }); // Filter for stale feeds const staleFeeds = feeds.filter(f => f.needsUpdate);
When to Use Compressors vs SDK
| Scenario | Approach |
|---|---|
| General market data | SDK marketRegister |
| Credit account queries | SDK services |
| Custom filtering logic | Direct compressor calls |
| Liquidation bots | Direct compressor (gas-optimized) |
| On-chain integration | Direct compressor (no SDK in contracts) |
| Real-time monitoring | Direct compressor with specific filters |
The SDK uses compressors internally. Use direct compressor calls when you need:
- Custom filter combinations not exposed by SDK
- Pagination control
- Gas-optimized queries for bots
- On-chain access (Solidity contracts)
Complete Example
TypeScript
TypeScript
import { createPublicClient, http } from 'viem'; import { mainnet } from 'viem/chains'; import { marketCompressorAbi, creditAccountCompressorAbi, } from '@gearbox-protocol/sdk'; const client = createPublicClient({ chain: mainnet, transport: http(), }); async function getMarketOverview() { const marketCompressor = '0x...'; // From AddressProvider const markets = await client.readContract({ address: marketCompressor, abi: marketCompressorAbi, functionName: 'getMarkets', args: [{ configurators: [], pools: [], underlying: '0x0000000000000000000000000000000000000000' }], }); for (const market of markets) { console.log(`Pool: ${market.pool.baseParams.addr}`); console.log(` Available: ${market.pool.availableLiquidity}`); console.log(` Supply Rate: ${market.pool.supplyRate}`); } } async function findLiquidatableAccounts(creditManager: `0x${string}`) { const accountCompressor = '0x...'; // From AddressProvider const [accounts] = await client.readContract({ address: accountCompressor, abi: creditAccountCompressorAbi, functionName: 'getCreditAccounts', args: [ creditManager, { owner: '0x0000000000000000000000000000000000000000', minHealthFactor: 0n, maxHealthFactor: 10000n, // HF < 1.0 includeZeroDebt: false, reverting: false, }, 0n, ], }); return accounts.filter(a => a.isLiquidatable); }
Solidity
Solidity
function getMarketData(address pool) external view returns (MarketData memory) { return IMarketCompressor(MARKET_COMPRESSOR).getMarketData(pool); } function findLiquidatableAccounts(address creditManager) external view returns (CreditAccountData[] memory) { CreditAccountFilter memory filter = CreditAccountFilter({ owner: address(0), minHealthFactor: 0, maxHealthFactor: 10000, includeZeroDebt: false, reverting: false }); (CreditAccountData[] memory accounts,) = ICreditAccountCompressor(ACCOUNT_COMPRESSOR).getCreditAccounts( creditManager, filter, 0 ); return accounts; }