back to docs
contributions

HunnySwap

Track HunnySwap DEX volume & fees

My seventh contribution to DefiLlama: tracking volume and fees for HunnySwap, a Uniswap V2 fork on Avalanche.

  • Protocol: HunnySwap
  • Type: DEX (Decentralized Exchange)
  • Chain: Avalanche
  • Start date: 2022-06-06
  • Approach: Uniswap V2 log adapter
Status

Status: Closed → Refactored by maintainer

My PR: #5415 (Closed)

Maintainer’s PR: #5433 Merged

Issue: Wrong folder placement (fees/ instead of dexs/)

1. Background story

a. Picking HunnySwap

HunnySwap is a Uniswap V2 fork on Avalanche. Since it’s a standard AMM DEX, I thought this would be straightforward:

  • Use getUniV2LogAdapter helper
  • Track swap volume and fees
  • HunnySwap docs clearly state fee breakdown

Fee structure from their docs:

  • 0.3% trading fee total
    • 0.18% → LPs (supply side)
    • 0.10% → gXOXO + LOVE stakers (holders)
    • 0.02% → Treasury (protocol)

2. My implementation (PR #5415)

a. The mistake: wrong folder

I placed my file in fees/hunnyswap.ts

// fees/hunnyswap.ts  ← WRONG LOCATION
import { FetchOptions, SimpleAdapter } from "../adapters/types";
import { CHAIN } from "../helpers/chains";
import { getUniV2LogAdapter } from "../helpers/uniswap";

const FACTORY = "0x0c6A0061F9D0afB30152b8761a273786e51bec6d";

const feesPercent = {
  Fees: 0.3,
  UserFees: 0.3,
  Revenue: 0.12, // gXOXO + LOVE + Treasury
  ProtocolRevenue: 0.02, // Treasury only
  HoldersRevenue: 0.1, // gXOXO + LOVE staking
  SupplySideRevenue: 0.18, // LP rewards
};

const adapter: SimpleAdapter = {
  version: 2,
  adapter: {
    [CHAIN.AVAX]: {
      fetch: async (options: FetchOptions) => {
        const res = await getUniV2LogAdapter({
          factory: FACTORY,
        })(options);

        return {
          dailyVolume: res.dailyVolume,
          dailyFees: res.dailyVolume.clone(feesPercent.Fees / 100),
          dailyUserFees: res.dailyVolume.clone(feesPercent.UserFees / 100),
          dailyRevenue: res.dailyVolume.clone(feesPercent.Revenue / 100),
          dailyProtocolRevenue: res.dailyVolume.clone(
            feesPercent.ProtocolRevenue / 100,
          ),
          dailyHoldersRevenue: res.dailyVolume.clone(
            feesPercent.HoldersRevenue / 100,
          ),
          dailySupplySideRevenue: res.dailyVolume.clone(
            feesPercent.SupplySideRevenue / 100,
          ),
        };
      },
      start: "2022-06-06",
    },
  },
};

b. Why this was wrong

DefiLlama folder structure:

dimension-adapters/
├── fees/           # For protocols that only charge fees (no volume)
├── dexs/           # For DEXes (track volume + fees)
├── aggregators/    # For DEX aggregators
└── derivatives/    # For derivatives protocols

HunnySwap is a DEX, so it should be in dexs/, not fees/!

The distinction:

  • fees/ → Protocols with fees but no tradeable volume (e.g., chain fees, lending protocol fees)
  • dexs/ → DEXes that have swap volume (the primary metric)

c. Test results

Despite wrong folder, tests worked:

> [email protected] test
> ts-node --transpile-only cli/testAdapter.ts fees hunnyswap.ts

🦙 Running HUNNYSWAP.TS adapter 🦙
---------------------------------------------------
Start Date:	Sun, 28 Dec 2025 10:55:47 GMT
End Date:	Mon, 29 Dec 2025 10:55:47 GMT
---------------------------------------------------

AVAX 👇
Backfill start time: 6/6/2022
Daily volume: 58.00
Daily fees: 0.00
Daily user fees: 0.00
Daily revenue: 0.00
Daily protocol revenue: 0.00
Daily holders revenue: 0.00
Daily supply side revenue: 0.00
End timestamp: 1767005746 (2025-12-29T10:55:46.000Z)

Volume tracked, but fees showing zero (likely no activity during test window).

3. The maintainer’s refactor (PR #5433)

a. Closed and redirected

bheluga closed my PR with:

“Thanks for the PR, tracked here #5433”

Then created PR #5433 with the correct implementation.

b. What changed

File location: dexs/hunnyswap.ts ← Correct folder!

Code structure: Simplified and cleaner

// dexs/hunnyswap.ts  ← CORRECT LOCATION
import { SimpleAdapter } from "../adapters/types";
import { CHAIN } from "../helpers/chains";
import { getUniV2LogAdapter } from "../helpers/uniswap";

const FACTORY = "0x0c6A0061F9D0afB30152b8761a273786e51bec6d";

const adapter: SimpleAdapter = {
  version: 2,
  methodology: {
    Fees: 'Users pay 0.3% per swap.',
    UserFees: 'Users pay 0.3% per swap.',
    SupplySideRevenue: '0.18% swap fees distributed to LPs.',
    Revenue: '0.12% swap fees goes to protocol and holders',
    ProtocolRevenue: '0.02% swap fees goes to treasury',
    HoldersRevenue: '0.1% swap fees goes to LOVE and gXOXO token stakers'
  },
  fetch: getUniV2LogAdapter({
    factory: FACTORY,
    userFeesRatio: 1,
    revenueRatio: 0.12 / 0.3,
    protocolRevenueRatio: 0.02 / 0.3,
    holdersRevenueRatio: 0.1 / 0.3
  }),
  chains: [CHAIN.AVAX],
  start: "2022-06-06",
}

c. Key improvements

AspectMy VersionFinal Version
Folderfees/dexs/
Structureadapter: { [CHAIN.AVAX]: { fetch, start } }fetch, chains, start (flat)
Fetch LogicManual calculation with .clone()Use helper params directly
Fee CalculationSeparate object, manual multiplyPass ratios to helper
MethodologyMissingDocumented

4. Understanding the refactor

a. Why folder matters

SEO and discoverability:

  • dexs/ adapters show up under “DEX” category
  • fees/ adapters show up under “Fees” category
  • Users looking for DEX volume won’t find it in fees/

Data structure expectations:

  • dexs/ adapters expected to return dailyVolume
  • fees/ adapters may not have volume

b. Simplified fetch logic

My approach (verbose):

fetch: async (options: FetchOptions) => {
  const res = await getUniV2LogAdapter({ factory: FACTORY })(options);

  return {
    dailyVolume: res.dailyVolume,
    dailyFees: res.dailyVolume.clone(feesPercent.Fees / 100),
    dailyUserFees: res.dailyVolume.clone(feesPercent.UserFees / 100),
    // ... more manual calculations
  };
}

Refactored approach (clean):

fetch: getUniV2LogAdapter({
  factory: FACTORY,
  userFeesRatio: 1,                    // 100% of fees are user fees
  revenueRatio: 0.12 / 0.3,            // 0.12 out of 0.3 = 40%
  protocolRevenueRatio: 0.02 / 0.3,    // 0.02 out of 0.3 = 6.67%
  holdersRevenueRatio: 0.1 / 0.3,      // 0.1 out of 0.3 = 33.33%
})

Why better:

  • Let the helper handle calculations
  • Ratios are relative to total fees (cleaner)
  • Less code, less room for error
  • No need for async wrapper

c. Methodology documentation

My version: Missing entirely

Final version:

methodology: {
  Fees: 'Users pay 0.3% per swap.',
  UserFees: 'Users pay 0.3% per swap.',
  SupplySideRevenue: '0.18% swap fees distributed to LPs.',
  Revenue: '0.12% swap fees goes to protocol and holders',
  ProtocolRevenue: '0.02% swap fees goes to treasury',
  HoldersRevenue: '0.1% swap fees goes to LOVE and gXOXO token stakers'
}

Clear documentation for users!

5. What I learned

a. Folder structure matters

Key lesson: Understand where different adapter types belong!

fees/        → Protocols with fees but no tradeable volume
dexs/        → DEXes (AMMs) - primary metric is volume
aggregators/ → DEX aggregators (1inch, ParaSwap)
derivatives/ → Perpetuals, options, futures

How to decide:

  • Does it have swap volume as primary metric? → dexs/
  • Is it just charging fees (chains, lending)? → fees/
  • Does it aggregate other DEXes? → aggregators/
  • Is it derivatives trading? → derivatives/

b. Use helper parameters

Don’t reinvent the wheel:

// Manual calculation
dailyFees: res.dailyVolume.clone(0.3 / 100)

// Use helper params
getUniV2LogAdapter({
  factory: FACTORY,
  userFeesRatio: 1,
  revenueRatio: 0.4,
})

Helpers are designed to handle common patterns. Use their parameters instead of manual calculations.

c. Methodology is required

From OpenTrade, I learned to add methodology. But I forgot to do it here!

Always include:

methodology: {
  Fees: "Explain fees",
  Revenue: "Explain revenue split",
  // ... other fields
}

6. Pattern recognition

This is similar to Variational:

  • PR closed
  • Code taken
  • Refactored by maintainer
  • Merged in new PR

Variational reason: Git workflow (couldn’t checkout master branch)

HunnySwap reason: Wrong folder structure

Both times: My approach was good, but placement/structure needed fixes.

7. Comparison with previous contributions

a. Evolution

  1. Taiko → Reviewer fixed calculation
  2. Bitfi → Closed, refactored (protocol slug confusion)
  3. Solomon → Fixed after feedback (revenue taxonomy)
  4. Variational → Closed (git workflow), code used
  5. Provenance → Merged as-is (milestone!)
  6. OpenTrade → Fixed after review (3 issues)
  7. HunnySwap → Closed (wrong folder), code refactored

b. New type of issue: folder structure

Each contribution teaches a different lesson:

  • Taiko: Fee calculations
  • Bitfi: Protocol slug structure
  • Solomon: Revenue taxonomy
  • Variational: Git workflow
  • Provenance: Production quality
  • OpenTrade: Cross-referencing, fee types
  • HunnySwap: Folder organization

8. Technical comparison

a. My implementation

// Pros:
Correct fee percentages
Proper use of getUniV2LogAdapter
Comprehensive fee breakdown

// Cons:
Wrong folder (fees/ instead of dexs/)
Manual .clone() calculations
No methodology documentation
Verbose structure

b. Final implementation

// Improvements:
Correct folder (dexs/)
Use helper parameters (ratios)
Methodology documented
Clean, simple structure

9. Resources

10. Key takeaways

a. What I got wrong

  1. Folder placement. Put DEX in fees/ instead of dexs/
  2. Over-engineering. Manual calculations instead of helper params
  3. Missing methodology. Forgot documentation

b. What I got right

  1. Correct fee percentages (from docs)
  2. Proper helper usage (getUniV2LogAdapter)
  3. Complete fee breakdown structure
  4. Correct start date

c. Key lessons

Understand folder structure:

Is it a DEX? → dexs/
Just fees? → fees/
Aggregator? → aggregators/

Use helper parameters:

// Don't manually calculate
// Let helpers do the work with ratios

Always document:

methodology: { ... } // Required!

d. The pattern continues

Like Variational and Bitfi:

  • PR closed
  • Code was good enough to use
  • Just needed structural fixes
  • Maintainer refactored and merged

Key insight: When maintainers take your code and refactor it, that’s validation. Your logic was sound, just needed organizational improvements.

Command Palette
Search for a command to run...