Bundle Method Overview
Overview
The bundle method represents a paradigm shift in how oracle data is delivered on Solana, eliminating write locks and reducing costs by 90%. With the new Ed25519 signature verification, bundles now require only 485 compute units for single feed verification, making them the most cost-efficient oracle solution on Solana.
🚀 No Data Feed Accounts Required
Unlike traditional oracle solutions, bundles require ZERO setup:
❌ No need to create data feed accounts
❌ No need to fund accounts with SOL
❌ No need to manage account permissions
✅ Just fetch a feed hash and start using prices immediately!
Why are bundles faster than other oracle solutions?
Traditional Approach (Higher Cost):
Oracle → Feed Account (write) → Your Program (read)
↑ Write Lock Required
Bundle Method (90% Lower Cost):
Oracle → Bundle → Your Program (direct use)
↑ No Write Lock!
Key Benefits
Transaction Cost
FREE
~0.0001 SOL
Compute Units
485 CU (1 feed)
1,000+ CU
Write Locks
None
Required
Parallelization
Unlimited
Limited
Setup Time
Instant
5-10 minutes
Maintenance
None
Crank required
How Bundles Work
1. Stateless Architecture
No data feed accounts - Start using prices without any account creation
No on-chain accounts to create or maintain
Prices are verified and used directly in your transaction
Multiple programs can read the same price simultaneously
2. Ultra-Efficient Ed25519 Signature Verification
The new Ed25519 verification system delivers unprecedented efficiency with only 485 compute units for single feed verification:
// Fetch the latest price bundle with Ed25519 optimization
const [sigVerifyIx, bundle] = await queue.fetchUpdateBundleIx(gateway, crossbar, [
feedHash1,
feedHash2,
// ... batch up to 8 feeds per oracle
]);
// Create transaction with minimal compute cost
const tx = await asV0Tx({
connection,
ixs: [
sigVerifyIx, // Ed25519 verification: ~485 CU for 1 feed
yourProgramIx // Use verified prices immediately
],
signers: [keypair],
computeUnitPrice: 10_000, // Optimized for low priority fees
});
Ed25519 Advantages:
Ultra-Low Cost: Only 485 compute units for single feed verification
Zero-Copy Parsing: No memory allocations during signature verification
Batch Validation: Single memcmp operation validates all oracle signatures
Variable Message Length: Supports any message size safely
3. Ultra-Fast On-Chain Verification
The Ed25519 verification process uses advanced optimizations for minimal compute cost:
// Ed25519 verification with zero-copy parsing and batch validation
let verified_bundle = BundleVerifierBuilder::from(&bundle)
.queue(&queue)
.slothash_sysvar(&slothashes)
.ix_sysvar(&instructions) // Ed25519 instruction parsing
.clock(&Clock::get()?)
.max_age(50) // Maximum age in slots
.verify() // Single memcmp validates all signatures
.unwrap();
// Extract verified price (zero allocation)
let price = verified_bundle.feed(FEED_HASH)?.value();
Verification Optimizations:
485 compute units for single feed verification
Zero-copy Ed25519 instruction parsing
Fixed-size validation arrays (no heap allocations)
Single memcmp operation validates all oracle signatures
Branchless bounds checking for maximum performance
Bundle Size Optimization
Understanding bundle sizes helps optimize your transactions with the new Ed25519 signature verification:
Ed25519 Instruction Size Formula
Updated Formula: Total bytes = 112 + 32 + (m × 49) + n + 9
Where:
112
= Ed25519 instruction base overhead32
= Slothash (signed message prefix)m
= number of feeds (49 bytes each)n
= number of oracle signatures9
= slot + version metadata
Feed Count Impact on Instruction Size
1 feed
203 bytes
205 bytes
207 bytes
3 feeds
301 bytes
303 bytes
305 bytes
5 feeds
399 bytes
401 bytes
403 bytes
8 feeds
546 bytes
548 bytes
550 bytes
Compute Unit Costs per Feed Count
The Ed25519 verification process has been optimized for ultra-low compute costs:
1 feed
485 CU
203-207 bytes
3 feeds
505 CU
301-305 bytes
5 feeds
520 CU
399-403 bytes
8 feeds
545 CU
546-550 bytes
Note: Verification costs only 485 compute units for single feed bundles, scaling to just 545 CU for 8 feeds, making them extremely cost-efficient compared to traditional oracle solutions.
Key Optimizations
Zero-Copy Parsing: Ed25519 instructions use ultra-efficient zero-copy parsing
Batch Validation: Single memcmp operation validates all oracle signatures
Fixed Buffer Sizes: Stack-allocated arrays eliminate heap allocations
Variable Message Length: Ed25519 safely supports any message length (unlike secp256k1)
Quick Start with Bundles
# Clone the examples repository
git clone https://github.com/switchboard-xyz/sb-on-demand-examples.git
cd sb-on-demand-examples/solana
# Install dependencies
bun install
# Run with your feed hash
bun run scripts/runBundle.ts --feedHash YOUR_FEED_HASH
Real-World Use Cases
DeFi Lending Protocol
pub fn liquidate_position(ctx: Context<Liquidate>, bundle: Vec<u8>) -> Result<()> {
// Verify the bundle
let verified_bundle = BundleVerifierBuilder::from(&bundle)
.queue(&ctx.accounts.queue)
.slothash_sysvar(&ctx.accounts.slothashes)
.ix_sysvar(&ctx.accounts.instructions)
.clock(&Clock::get()?)
.max_age(50)
.verify()?;
// Extract BTC price
let btc_feed = verified_bundle.feed(BTC_FEED_ID)?;
let btc_price = btc_feed.value();
// Check if position is underwater
let ltv = calculate_ltv(ctx.accounts.position, btc_price);
require!(ltv > LIQUIDATION_THRESHOLD, ErrorCode::PositionHealthy);
// Execute liquidation...
}
Perpetual DEX
async function executeTrade(
amount: number,
leverage: number,
feedHashes: string[]
) {
// Fetch multiple prices in one bundle
const [sigVerifyIx, bundle] = await queue.fetchUpdateBundleIx(
gateway,
crossbar,
feedHashes // ["BTC/USD", "ETH/USD", "SOL/USD"]
);
// Create your trading instruction
const tradeIx = await program.methods
.openPosition(amount, leverage, bundle)
.accounts({
trader: wallet.publicKey,
market: marketPda,
queue: queue.pubkey,
// ... other accounts
})
.instruction();
// Execute atomically
const tx = await asV0Tx({
connection,
ixs: [sigVerifyIx, tradeIx],
signers: [wallet],
computeUnitPrice: 50_000, // Higher priority for MEV protection
});
await connection.sendTransaction(tx);
}
Stablecoin Minting
async function mintStablecoin(collateralAmount: number) {
// Fetch collateral asset prices
const collateralFeeds = [
"0x...", // wBTC feed hash
"0x...", // wETH feed hash
"0x...", // SOL feed hash
];
const [sigVerifyIx, bundle] = await queue.fetchUpdateBundleIx(
gateway,
crossbar,
collateralFeeds
);
const mintIx = await stablecoinProgram.methods
.mint(collateralAmount, bundle)
.accounts({
user: wallet.publicKey,
collateralVault: vaultPda,
mintAuthority: mintAuthorityPda,
queue: queue.pubkey,
slothashes: SYSVAR_SLOT_HASHES_PUBKEY,
instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
})
.instruction();
// Bundle verification + minting in one atomic transaction
const tx = await asV0Tx({
connection,
ixs: [sigVerifyIx, mintIx],
signers: [wallet],
});
const sig = await connection.sendTransaction(tx);
}
When to Use Bundles
Smart contract integrations
DeFi protocols requiring multiple price points
Cost-sensitive applications
Standard trading applications
Current Limits
Rate Limit: 30 requests per minute
Cost: FREE during launch phase
No maintenance: No cranks or accounts needed
Getting Started
Get a feed hash from Switchboard Bundle Builder
Use the bundle examples: GitHub Repository
Integrate into your program using the verification pattern
Next Steps
Last updated