Skip to Content
Welcome to the DuckyDux Docs! 🦆
GuidesGas Sponsorship Guide

Gas Sponsorship Guide

DuckyDux’s gas sponsorship system enables truly gasless experiences for your users by allowing you to pay transaction fees on their behalf with automatic repayment.

Unique Feature: DuckyDux’s sponsorship model automatically handles gas estimation, repayment calculation, and execution - no complex smart contracts required.

How Gas Sponsorship Works

User initiates transaction

User creates a transaction but doesn’t need ETH for gas

DuckyDux sponsor contract covers the gas costs

Automatic repayment

User repays sponsor in the same transaction using token proceeds

Sponsorship Flow

// Get sponsorship quote const sponsorshipQuote = await fetch('https://api.duckydux.com/v1/bundles/quote', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ accounts: ['0x123...abc'], // Users to sponsor amounts: ['1000000000000000000'] // 1 ETH worth of gas }) }); const quote = await sponsorshipQuote.json();

Sponsorship Quote Structure

FieldDescriptionExample
repaymentAmountAmount user must repay1050000000000000000
maxFeePerGasMaximum gas price used20000000000
feePercentSponsorship fee percentage5.0
sponsorAddressContract handling sponsorship0xabc...

Complete Sponsored Swap Example

Get Swap Quote with Sponsorship

const swapQuote = await fetch('https://api.duckydux.com/v1/swap/quote?' + new URLSearchParams({ sources: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC sinks: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH supplies: '1000000000', // 1000 USDC demands: '-1', slippage: '0.5', sender: userAddress, sponsorship: 'true', // Enable sponsorship data check_approvals: 'true' })); const quote = await swapQuote.json();

When sponsorship=true, the swap quote includes sponsorship information automatically calculated based on the transaction requirements.

Sign User Transactions

The API response provides all the necessary transactions with sequential nonces and EIP-1559 gas parameters pre-populated. The user does not need ETH for gas. Sign each transaction as provided.

const signedTxs = [] // Sign approval transaction (if needed) if (quote.approvals.length > 0) { const signedApproval = await web3.eth.accounts.signTransaction( quote.approvals[0].tx, userPrivateKey ) signedTxs.push(signedApproval.rawTransaction) } // Sign swap transaction(s) for (const tx of quote.txs) { const signedSwap = await web3.eth.accounts.signTransaction(tx, userPrivateKey) signedTxs.push(signedSwap.rawTransaction) }

Submit Sponsored Bundle

const sponsorship = quote.sponsorship // Sponsorship data from the swap quote const bundleResponse = await fetch('https://api.duckydux.com/v1/bundles/sponsored/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ accounts: [userAddress], amounts: [sponsorship.sponsorAmount], repayments: [sponsorship.repaymentAmount], maxFeePerGas: sponsorship.maxFeePerGas, txs: signedTxs, }), }) const result = await bundleResponse.json() console.log('Sponsored bundle submitted:', result.bundleId)

Sponsorship Economics

Fee Structure

Important: Sponsorship fees typically range from 5-10% of the gas cost, covering operational costs and risk premium.

// Example fee calculation const gasAmount = '1000000000000000000' // 1 ETH worth of gas const feePercent = 5.0 // 5% fee const repaymentAmount = gasAmount * (1 + feePercent / 100) // User repays 1.05 ETH for 1 ETH of sponsored gas

Repayment Logic

The sponsorship system automatically handles repayment through these mechanisms:

  1. Token-to-ETH conversion: If user receives ETH from swap, direct repayment
  2. Multi-token repayment: System accepts repayment in various tokens
  3. Slippage protection: Repayment amount accounts for potential slippage

On-Chain Repayment Mechanism

The GasSponsor smart contract facilitates atomic and secure repayments. When a user’s transaction is sponsored, a debt is recorded on-chain. The user can repay this debt by sending ETH directly to the GasSponsor contract.

The contract’s receive() function is designed to handle these payments:

receive() external payable nonReentrant { Debt memory debt = debts[msg.sender]; if (debt.amount > 0) { _executeRepayment(msg.sender, debt, msg.value); } }

This ensures that when ETH is sent to the contract, it automatically checks for an outstanding debt for the sender and processes the repayment. The _executeRepayment function verifies that the paid amount is sufficient, clears the debt, and forwards the funds to the original relayer, making the process transparent and secure.

Risk Management

RiskMitigationImplementation
Insufficient repaymentPre-calculate exact amountsUse quote system
Gas price volatilityFixed max fee per gasSet in quote
Transaction failureAtomic bundle executionAll-or-nothing
SlippageInclude safety marginBuffer in repayment

Integration Patterns

// Frontend: Gasless user experience class DuckyDuxGaslessSwap { async executeSwap(fromToken, toToken, amount) { // 1. Get swap quote with sponsorship const quote = await this.getQuoteWithSponsorship(fromToken, toToken, amount); // 2. User signs transactions (zero gas) const signedTxs = await this.signTransactions(quote); // 3. Submit sponsored bundle const result = await this.submitSponsoredBundle(signedTxs, quote.sponsorship); return result; } }

Common Issues and Solutions

Common Pitfall: Not accounting for gas price fluctuations. Always use the maxFeePerGas from the sponsorship quote.

Insufficient Repayment

Problem: User doesn’t receive enough tokens to cover repayment

Solution: Add safety margins and slippage buffers

// Add 5% buffer to repayment calculation const bufferedRepayment = sponsorship.repaymentAmount * 1.05

Gas Price Volatility

Problem: Gas prices spike after getting quote

Solution: Use recent quotes and appropriate max fee per gas

// Refresh quotes frequently in volatile conditions const isVolatile = currentGasPrice > averageGasPrice * 1.5 if (isVolatile) { // Get fresh quote const newQuote = await getSponsorshipQuote() }

Bundle Failures

Problem: Sponsored bundle fails to execute

Solution: Implement retry logic with updated parameters

async function submitSponsorshipWithRetry(bundleData, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const result = await submitSponsoredBundle(bundleData) return result } catch (error) { if (i === maxRetries - 1) throw error // Update gas parameters for retry bundleData = await updateGasParameters(bundleData) } } }

Next Steps

Last updated on