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
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
getUniV2LogAdapterhelper - 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
| Aspect | My Version | Final Version |
|---|---|---|
| Folder | fees/ | dexs/ |
| Structure | adapter: { [CHAIN.AVAX]: { fetch, start } } | fetch, chains, start (flat) |
| Fetch Logic | Manual calculation with .clone() | Use helper params directly |
| Fee Calculation | Separate object, manual multiply | Pass ratios to helper |
| Methodology | Missing | Documented |
4. Understanding the refactor
a. Why folder matters
SEO and discoverability:
dexs/adapters show up under “DEX” categoryfees/adapters show up under “Fees” category- Users looking for DEX volume won’t find it in
fees/
Data structure expectations:
dexs/adapters expected to returndailyVolumefees/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
- Taiko → Reviewer fixed calculation
- Bitfi → Closed, refactored (protocol slug confusion)
- Solomon → Fixed after feedback (revenue taxonomy)
- Variational → Closed (git workflow), code used
- Provenance → Merged as-is (milestone!)
- OpenTrade → Fixed after review (3 issues)
- 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
- Folder placement. Put DEX in
fees/instead ofdexs/ - Over-engineering. Manual calculations instead of helper params
- Missing methodology. Forgot documentation
b. What I got right
- Correct fee percentages (from docs)
- Proper helper usage (
getUniV2LogAdapter) - Complete fee breakdown structure
- 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.