Updated Yield Averaging to correctly match the yield distributed#6292
Updated Yield Averaging to correctly match the yield distributed#6292neelra8n wants to merge 13 commits intoDefiLlama:masterfrom
Conversation
📝 WalkthroughWalkthroughThe fee calculation mechanism for YieldFi vaults has been redesigned to use multi-block sampling instead of single-point snapshots. Vault discovery now operates through segmented block ranges with deduplication, and fee accumulation computes values across sub-intervals using averaged supply and rate deltas. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Worker as Fee Processor
participant Discover as Vault Discovery
participant Chain as Blockchain
participant Sample as Multi-Block Sampler
participant Fee as Fee Accumulator
Worker->>Discover: fetchVaultDeployedLogs(options, vaultDeployer)
Discover->>Discover: Compute scan window from PROTOCOL_START_TS
Discover->>Chain: Query ABI.DEPLOY_VAULT logs in YIELD_SEGMENTS chunks
Chain-->>Discover: Return deployment logs
Discover->>Discover: Deduplicate vaults by address
Discover-->>Worker: Merged, deduplicated vault list
Worker->>Sample: Split [getFromBlock, getToBlock] into YIELD_SEGMENTS
Sample->>Sample: Build boundaryBlocks array
loop For each boundary
Sample->>Chain: multiCall(totalSupply, getRate, block)
Chain-->>Sample: Values at boundary
Sample->>Sample: Collect snapshot
end
Sample-->>Worker: Block-boundary snapshots
Worker->>Fee: Accumulate fees per vault/segment
loop For each vault and sub-interval
Fee->>Fee: avgSupply = (s0+s1)/2
Fee->>Fee: rateDelta = r1-r0
Fee->>Fee: Compute fee with decimals scaling
Fee->>Fee: Skip if null, add if non-zero
end
Fee-->>Worker: Final accumulated fees
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
The yieldfi adapter exports: |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@fees/yieldfi/index.ts`:
- Around line 39-55: The code assumes deployFromBlock (from options.getBlock) is
non-null and then computes a huge span; add a null guard and a scan-cap before
chunking: if deployFromBlock is null (or options.getToBlock() is null) return []
or compute a safe fallback window instead of using genesis (do not let
deployFromBlock be treated as 0), and introduce a MAX_SCAN_BLOCKS cap so span =
Math.min(toBlock - deployFromBlock, MAX_SCAN_BLOCKS) before calculating
chunkFrom/chunkTo; keep using YIELD_SEGMENTS to split that capped span and pass
those chunkFrom/chunkTo into options.getLogs (symbols: deployFromBlock,
options.getBlock, options.getToBlock, YIELD_SEGMENTS, chunkFrom, chunkTo,
options.getLogs).
- Around line 121-132: The loop currently converts supplies/rates to Number and
uses floating math (loss of precision for 1e18); change the accumulation to use
bigint math: convert s0,s1,r0,r1 from suppliesAt and ratesAt into BigInt,
compute avgSupply = (s0 + s1) / 2n and rateDelta = r1 - r0 as BigInt, then
perform all scaling with BigInt power expressions (e.g., 10n **
BigInt(decimals[i]) and 10n ** BigInt(decimals[i] - assetDecimals[i])) to
compute acc as a BigInt; only convert to the expected type when calling
dailyFees.add (or adjust dailyFees.add to accept BigInt) and use acc !== 0n for
the nonzero check. Ensure you reference YIELD_SEGMENTS, suppliesAt, ratesAt,
decimals, assetDecimals, acc, and dailyFees.add when applying the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| const deployFromBlock = await options.getBlock(startTs, options.chain, {}) | ||
| const toBlock = await options.getToBlock() | ||
| if (deployFromBlock > toBlock) return [] | ||
| const span = toBlock - deployFromBlock | ||
| const seen = new Set<string>() | ||
| const merged: any[] = [] | ||
| for (let i = 0; i < YIELD_SEGMENTS; i++) { | ||
| const chunkFrom = deployFromBlock + Math.floor((i * span) / YIELD_SEGMENTS) | ||
| const chunkTo = i === YIELD_SEGMENTS - 1 ? toBlock : deployFromBlock + Math.floor(((i + 1) * span) / YIELD_SEGMENTS) - 1 | ||
| if (chunkFrom > chunkTo) continue | ||
| const chunkLogs = await options.getLogs({ | ||
| target: vaultDeployer, | ||
| eventAbi: ABI.DEPLOY_VAULT, | ||
| cacheInCloud: true, | ||
| fromBlock: chunkFrom, | ||
| toBlock: chunkTo, | ||
| }) |
There was a problem hiding this comment.
Handle failed block resolution and cap the discovery scan.
helpers/getBlock.ts can return null on Line 39. If that happens, the range math below degenerates into a genesis-sized scan, and even the non-null path still splits the full protocol lifetime into only 10 getLogs windows. CI is already failing on BSC with pruned-history / limit errors, so this needs a null guard plus block-span-based chunking.
Possible fix
const startTs = PROTOCOL_START_TS[options.chain]
if (startTs === undefined) return []
const deployFromBlock = await options.getBlock(startTs, options.chain, {})
const toBlock = await options.getToBlock()
- if (deployFromBlock > toBlock) return []
- const span = toBlock - deployFromBlock
+ if (deployFromBlock == null || deployFromBlock > toBlock) return []
+ const maxBlockSpan = 50_000
const seen = new Set<string>()
const merged: any[] = []
- for (let i = 0; i < YIELD_SEGMENTS; i++) {
- const chunkFrom = deployFromBlock + Math.floor((i * span) / YIELD_SEGMENTS)
- const chunkTo = i === YIELD_SEGMENTS - 1 ? toBlock : deployFromBlock + Math.floor(((i + 1) * span) / YIELD_SEGMENTS) - 1
+ for (let chunkFrom = deployFromBlock; chunkFrom <= toBlock; chunkFrom += maxBlockSpan) {
+ const chunkTo = Math.min(chunkFrom + maxBlockSpan - 1, toBlock)
if (chunkFrom > chunkTo) continue
const chunkLogs = await options.getLogs({🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@fees/yieldfi/index.ts` around lines 39 - 55, The code assumes deployFromBlock
(from options.getBlock) is non-null and then computes a huge span; add a null
guard and a scan-cap before chunking: if deployFromBlock is null (or
options.getToBlock() is null) return [] or compute a safe fallback window
instead of using genesis (do not let deployFromBlock be treated as 0), and
introduce a MAX_SCAN_BLOCKS cap so span = Math.min(toBlock - deployFromBlock,
MAX_SCAN_BLOCKS) before calculating chunkFrom/chunkTo; keep using YIELD_SEGMENTS
to split that capped span and pass those chunkFrom/chunkTo into options.getLogs
(symbols: deployFromBlock, options.getBlock, options.getToBlock, YIELD_SEGMENTS,
chunkFrom, chunkTo, options.getLogs).
| let acc = 0; | ||
| for (let k = 0; k < YIELD_SEGMENTS; k++) { | ||
| const s0 = suppliesAt[k][i]; | ||
| const s1 = suppliesAt[k + 1][i]; | ||
| const r0 = ratesAt[k][i]; | ||
| const r1 = ratesAt[k + 1][i]; | ||
| if (s0 == null || s1 == null || r0 == null || r1 == null) continue; | ||
| const avgSupply = (Number(s0) + Number(s1)) / 2; | ||
| const rateDelta = Number(r1) - Number(r0); | ||
| acc += (avgSupply / 10 ** decimals[i]) * rateDelta / 10 ** (decimals[i] - assetDecimals[i]); | ||
| } | ||
| if (acc !== 0) dailyFees.add(assets[i], acc); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Python float uses the same IEEE-754 double-precision model as JS Number.
python - <<'PY'
max_safe = 2**53 - 1
print("max safe integer:", max_safe)
for raw in (10**18, 10**18 + 1, 10**23, 10**23 + 1):
print(f"{raw}: float(raw) == float(raw + 1) -> {float(raw) == float(raw + 1)}")
PYRepository: DefiLlama/dimension-adapters
Length of output: 349
🏁 Script executed:
# Find the yieldfi index file and examine the code around lines 121-132
find . -path "*fees/yieldfi/index.ts" -type fRepository: DefiLlama/dimension-adapters
Length of output: 95
🏁 Script executed:
# Check the code at the specified lines
if [ -f "fees/yieldfi/index.ts" ]; then
wc -l fees/yieldfi/index.ts
echo "=== Lines 115-140 ==="
sed -n '115,140p' fees/yieldfi/index.ts
fiRepository: DefiLlama/dimension-adapters
Length of output: 1405
🏁 Script executed:
# Also check what dailyFees is and what its add method expects
rg -A 5 "dailyFees\s*=" fees/yieldfi/index.ts | head -20Repository: DefiLlama/dimension-adapters
Length of output: 350
🏁 Script executed:
# Check the file structure and imports to understand data types
head -50 fees/yieldfi/index.tsRepository: DefiLlama/dimension-adapters
Length of output: 2564
🏁 Script executed:
# Find the Balances type definition
rg -r "class Balances" --type ts | head -5Repository: DefiLlama/dimension-adapters
Length of output: 468
🏁 Script executed:
# Also check the adapters/types file
if [ -f "adapters/types.ts" ]; then
rg "class Balances|interface.*Balances|add\(" adapters/types.ts | head -20
fiRepository: DefiLlama/dimension-adapters
Length of output: 54
🏁 Script executed:
# Search more broadly for Balances definition
find . -name "*.ts" -type f -exec grep -l "class Balances" {} \; 2>/dev/null | head -5Repository: DefiLlama/dimension-adapters
Length of output: 54
🏁 Script executed:
# Check helper files for Balances
ls -la helpers/Repository: DefiLlama/dimension-adapters
Length of output: 3931
🏁 Script executed:
# Search for Balances class in adapters directory
find . -name "*.ts" -type f | xargs grep -l "class Balances" 2>/dev/nullRepository: DefiLlama/dimension-adapters
Length of output: 56
🏁 Script executed:
# Look in the main adapters directory
find adapters -name "*.ts" -type f | xargs grep -l "class Balances" 2>/dev/nullRepository: DefiLlama/dimension-adapters
Length of output: 56
🏁 Script executed:
# Try a different approach - search for the add method definition
rg "add\s*\(" adapters/types.tsRepository: DefiLlama/dimension-adapters
Length of output: 54
🏁 Script executed:
# Check adapters/types.ts directly
if [ -f "adapters/types.ts" ]; then
wc -l adapters/types.ts
fiRepository: DefiLlama/dimension-adapters
Length of output: 93
🏁 Script executed:
# Read adapters/types.ts to find Balances
head -200 adapters/types.ts | tail -100Repository: DefiLlama/dimension-adapters
Length of output: 3325
🏁 Script executed:
# Check the beginning of adapters/types.ts for imports
head -50 adapters/types.tsRepository: DefiLlama/dimension-adapters
Length of output: 1666
🏁 Script executed:
# Search for where Balances is imported from in adapters/types.ts
grep "import.*Balances\|from.*Balances" adapters/types.tsRepository: DefiLlama/dimension-adapters
Length of output: 130
🏁 Script executed:
# Try searching in the entire codebase for Balances class definition
find . -type f -name "*.ts" | head -50 | xargs grep -l "export.*class Balances" 2>/dev/nullRepository: DefiLlama/dimension-adapters
Length of output: 56
🏁 Script executed:
# Check if it's in a sdk or external package - search package.json
cat package.json | grep -A 50 '"dependencies"'Repository: DefiLlama/dimension-adapters
Length of output: 772
🏁 Script executed:
# Search for usages of .add() on Balances-like objects in the codebase
rg "\.add\(" fees/ | head -30Repository: DefiLlama/dimension-adapters
Length of output: 2716
🏁 Script executed:
# Look specifically at how dailyFees.add is used in yieldfi
grep -A 2 -B 2 "dailyFees.add" fees/yieldfi/index.tsRepository: DefiLlama/dimension-adapters
Length of output: 866
🏁 Script executed:
# Check if there are any other files that use .add() with stringified values
rg "\.add\([^,]+,\s*['\"].*\.toString\(\)" fees/ | head -10Repository: DefiLlama/dimension-adapters
Length of output: 54
🏁 Script executed:
# Look at other fee adapters to understand the pattern
rg "dailyFees\.add\(" fees/ | head -20Repository: DefiLlama/dimension-adapters
Length of output: 1739
🏁 Script executed:
# Check if yieldfi adapter has allowNegativeValue
grep -n "allowNegativeValue" fees/yieldfi/index.tsRepository: DefiLlama/dimension-adapters
Length of output: 123
🏁 Script executed:
# Check what types suppliesAt and ratesAt actually contain
grep -B 5 -A 5 "suppliesAt\|ratesAt" fees/yieldfi/index.ts | head -40Repository: DefiLlama/dimension-adapters
Length of output: 1432
🏁 Script executed:
# Look for the export/return statement to see the adapter config
tail -20 fees/yieldfi/index.tsRepository: DefiLlama/dimension-adapters
Length of output: 412
🏁 Script executed:
# Check if Balances.add accepts strings or numbers - search for documentation or method signature
rg "interface.*Balances|\.add.*:" adapters/ --type ts | head -20Repository: DefiLlama/dimension-adapters
Length of output: 445
🏁 Script executed:
# Look at similar fee calculations to understand the pattern better
grep -B 5 -A 5 "avgSupply\|rateDelta" fees/ --include="*.ts" | head -50Repository: DefiLlama/dimension-adapters
Length of output: 99
🏁 Script executed:
# Check what multiCall returns by looking at examples
grep -B 2 -A 5 "\.multiCall" fees/yieldfi/index.ts | head -30Repository: DefiLlama/dimension-adapters
Length of output: 1227
🏁 Script executed:
# Look at the external SDK - check package and understand multiCall return type
rg "multiCall.*uint256" fees/ --type ts | head -5Repository: DefiLlama/dimension-adapters
Length of output: 891
🏁 Script executed:
# Check actual usage in other files to see what type is returned
rg "multiCall.*uint256" . --type ts -B 2 -A 2 | head -50Repository: DefiLlama/dimension-adapters
Length of output: 5018
🏁 Script executed:
# Search for how other adapters handle bigint/number conversions for fees
rg "BigInt.*add|acc.*=.*0n" fees/ --type ts | head -20Repository: DefiLlama/dimension-adapters
Length of output: 644
🏁 Script executed:
# Look at how other adapters with large decimals handle precision
grep -r "toFixed\|toString\|BigInt" fees/ --include="*.ts" | grep -i "fees\|revenue" | head -20Repository: DefiLlama/dimension-adapters
Length of output: 1615
🏁 Script executed:
# Let's understand what Balances.add() accepts by checking if there are any TypeScript definitions
rg "\.add\(" --type ts -A 2 | grep -E "string|number|bigint" | head -20Repository: DefiLlama/dimension-adapters
Length of output: 747
🏁 Script executed:
# Check if the proposed fix's BigInt math is mathematically sound
python3 <<'EOF'
# Test the proposed fix logic for accuracy
# Original: (avgSupply / 10^decimals) * rateDelta / 10^(decimals - assetDecimals)
# Proposed: (supplySum * rateDelta) / (2 * 10^exponent) where exponent = 2*decimals - assetDecimals
# Example: decimals = 18, assetDecimals = 6
decimals = 18
assetDecimals = 6
exponent = 2 * decimals - assetDecimals # 30
# Test with sample values
s0 = 10**18
s1 = 10**18
r0 = 10**9
r1 = 10**9 + 1
# Original calculation (in float)
avgSupply = (s0 + s1) / 2
rateDelta = r1 - r0
original_result = (avgSupply / 10 ** decimals) * rateDelta / 10 ** (decimals - assetDecimals)
# Proposed calculation (in bigint)
supplySum = s0 + s1
rateDelta_bi = r1 - r0
exponent = 2 * decimals - assetDecimals
if exponent >= 0:
segmentAcc = (supplySum * rateDelta_bi) // (2 * 10 ** exponent)
else:
segmentAcc = (supplySum * rateDelta_bi * 10 ** (-exponent)) // 2
print(f"Original (float): {original_result}")
print(f"Proposed (bigint, stringified): {str(segmentAcc)}")
print(f"Match: {original_result == float(segmentAcc)}")
print(f"\nPrecision difference: {abs(original_result - float(segmentAcc))}")
EOFRepository: DefiLlama/dimension-adapters
Length of output: 171
🏁 Script executed:
# Check what Balances is and what methods it accepts
# Search for documentation or examples that pass strings to add()
rg "dailyFees\.add.*toString\|add.*\.toString" fees/ --type tsRepository: DefiLlama/dimension-adapters
Length of output: 54
🏁 Script executed:
# Look more carefully at Balances usage - does it accept bigint or strings?
rg "\.add\(" fees/ --type ts -B 2 -A 1 | grep -E "\.add\(.*0n|\.add\(.*BigInt" | head -20Repository: DefiLlama/dimension-adapters
Length of output: 2009
🏁 Script executed:
# Check if there are examples of passing bigint values to .add()
rg "\.add\([^,]+,\s*(0n|BigInt|[0-9]+n)" . --type ts | head -15Repository: DefiLlama/dimension-adapters
Length of output: 1920
🏁 Script executed:
# Look at what types multiCall returns - check SDK usage more carefully
rg "multiCall.*uint256" fees/yieldfi/ --type ts -A 5 -B 2Repository: DefiLlama/dimension-adapters
Length of output: 786
🏁 Script executed:
# Test the precision issue more comprehensively for various decimal combinations
python3 <<'EOF'
# Test precision for different decimal combinations that would occur in practice
test_cases = [
# (decimals, assetDecimals, s0, s1, r0, r1, description)
(18, 6, 10**18, 10**18 + 1000, 10**9, 10**9 + 1, "18-decimal vault"),
(8, 6, 10**8, 10**8 + 100, 10**5, 10**5 + 1, "8-decimal vault"),
(6, 6, 10**6, 10**6 + 10, 10**3, 10**3 + 1, "6-decimal vault"),
]
for decimals, assetDecimals, s0, s1, r0, r1, desc in test_cases:
# Original (float)
avgSupply = (s0 + s1) / 2
rateDelta = r1 - r0
original = (avgSupply / 10 ** decimals) * rateDelta / 10 ** (decimals - assetDecimals)
# Proposed (bigint with integer division)
supplySum = s0 + s1
rateDelta_bi = r1 - r0
exponent = 2 * decimals - assetDecimals
if exponent >= 0:
proposed = (supplySum * rateDelta_bi) // (2 * (10 ** exponent))
else:
proposed = ((supplySum * rateDelta_bi) * (10 ** (-exponent))) // 2
print(f"\n{desc}:")
print(f" Original (float): {original}")
print(f" Proposed (bigint): {proposed}")
print(f" Precision loss: {original - proposed}")
print(f" Match: {original == proposed}")
EOFRepository: DefiLlama/dimension-adapters
Length of output: 473
🏁 Script executed:
# Check if there's a type definition for Balances.add() signature in the SDK
# or if we can infer from documentation
rg "add.*\(.*\)" . --type ts -B 2 -A 2 | grep -E "add\s*\([^)]*:\s*(number|string|bigint)" | head -10Repository: DefiLlama/dimension-adapters
Length of output: 54
🏁 Script executed:
# Check the fragment/index.ts mentioned in learnings to see if it uses a similar pattern
if [ -f "fees/fragment/index.ts" ]; then
sed -n '95,110p' fees/fragment/index.ts
fiRepository: DefiLlama/dimension-adapters
Length of output: 1176
🏁 Script executed:
# Verify whether stringification is actually needed - test if bigint is passed directly elsewhere
rg "\.add\([^,]+,\s*[a-zA-Z_][a-zA-Z0-9_]*n\s*\)" . --type ts | head -10Repository: DefiLlama/dimension-adapters
Length of output: 426
🏁 Script executed:
# Look at the exact math one more time - check if there's a better approach
# Let's see if the calculation can be kept in bigint without stringification
python3 <<'EOF'
# Test if we can keep bigint arithmetic without stringification
# and what the actual impact is
# Case: 18-decimal vault with assetDecimals = 6
decimals = 18
assetDecimals = 6
s0_raw = 10**18
s1_raw = 10**18
r0_raw = 10**9
r1_raw = 10**9 + 1
# Original code path (problematic precision)
avgSupply_float = (float(s0_raw) + float(s1_raw)) / 2
rateDelta_float = float(r1_raw) - float(r0_raw)
original = (avgSupply_float / 10 ** decimals) * rateDelta_float / 10 ** (decimals - assetDecimals)
print(f"Original calculation (float): {original}")
print(f"Original (scientific): {original:.20e}")
# Better approach: keep in bigint but use different division strategy
# Instead of: (sum * delta) / (2 * 10^exponent)
# We could do: (sum * delta) / (2) / 10^exponent
# But this still loses precision with integer division
# Or even better: accumulate in base units and scale at the end
supplySum = s0_raw + s1_raw
rateDelta = r1_raw - r0_raw
# This is raw: (supply * rate_change) - but we need to divide by 2 and apply decimals
# If we keep as bigint: supplySum * rateDelta = 2e18 * 1 = 2e18
result_raw = (supplySum * rateDelta) // 2 # = 1e18
# Now we need to scale: divide by 10^decimals and by 10^(decimals - assetDecimals)
# Total scale: 10^(decimals + decimals - assetDecimals) = 10^(2*18 - 6) = 10^30
final_scaled = result_raw / (10 ** 30)
print(f"\nBetter bigint approach: {final_scaled}")
print(f"Better (scientific): {final_scaled:.20e}")
# The real question: is this precision loss acceptable?
# For yield farming, typically dealing with raw amounts anyway
EOFRepository: DefiLlama/dimension-adapters
Length of output: 236
🏁 Script executed:
# Final check: verify the adapter's allowNegativeValue setting one more time
grep -B 5 -A 5 "allowNegativeValue" fees/yieldfi/index.tsRepository: DefiLlama/dimension-adapters
Length of output: 328
🏁 Script executed:
# Check if there are any tests or comments about expected precision
grep -r "precision\|BigInt\|Number.*conversion" fees/yieldfi/ --include="*.ts"Repository: DefiLlama/dimension-adapters
Length of output: 54
Keep raw token math in bigint.
Lines 128–130 convert raw supply/rate values to Number and then scale them with floating-point math. For 18-decimal vaults, 1e18 exceeds the safe-integer range (2^53 - 1), so this loses precision and can feed fractional raw amounts into dailyFees.add. Keep the accumulation in integer space.
Possible fix
- let acc = 0;
+ let acc = 0n;
for (let k = 0; k < YIELD_SEGMENTS; k++) {
const s0 = suppliesAt[k][i];
const s1 = suppliesAt[k + 1][i];
const r0 = ratesAt[k][i];
const r1 = ratesAt[k + 1][i];
if (s0 == null || s1 == null || r0 == null || r1 == null) continue;
- const avgSupply = (Number(s0) + Number(s1)) / 2;
- const rateDelta = Number(r1) - Number(r0);
- acc += (avgSupply / 10 ** decimals[i]) * rateDelta / 10 ** (decimals[i] - assetDecimals[i]);
+ const supplySum = BigInt(s0) + BigInt(s1);
+ const rateDelta = BigInt(r1) - BigInt(r0);
+ const exponent = 2n * BigInt(decimals[i]) - BigInt(assetDecimals[i]);
+ acc += (supplySum * rateDelta) / (2n * 10n ** exponent);
}
- if (acc !== 0) dailyFees.add(assets[i], acc);
+ if (acc !== 0n) dailyFees.add(assets[i], acc);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let acc = 0; | |
| for (let k = 0; k < YIELD_SEGMENTS; k++) { | |
| const s0 = suppliesAt[k][i]; | |
| const s1 = suppliesAt[k + 1][i]; | |
| const r0 = ratesAt[k][i]; | |
| const r1 = ratesAt[k + 1][i]; | |
| if (s0 == null || s1 == null || r0 == null || r1 == null) continue; | |
| const avgSupply = (Number(s0) + Number(s1)) / 2; | |
| const rateDelta = Number(r1) - Number(r0); | |
| acc += (avgSupply / 10 ** decimals[i]) * rateDelta / 10 ** (decimals[i] - assetDecimals[i]); | |
| } | |
| if (acc !== 0) dailyFees.add(assets[i], acc); | |
| let acc = 0n; | |
| for (let k = 0; k < YIELD_SEGMENTS; k++) { | |
| const s0 = suppliesAt[k][i]; | |
| const s1 = suppliesAt[k + 1][i]; | |
| const r0 = ratesAt[k][i]; | |
| const r1 = ratesAt[k + 1][i]; | |
| if (s0 == null || s1 == null || r0 == null || r1 == null) continue; | |
| const supplySum = BigInt(s0) + BigInt(s1); | |
| const rateDelta = BigInt(r1) - BigInt(r0); | |
| const exponent = 2n * BigInt(decimals[i]) - BigInt(assetDecimals[i]); | |
| acc += (supplySum * rateDelta) / (2n * 10n ** exponent); | |
| } | |
| if (acc !== 0n) dailyFees.add(assets[i], acc); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@fees/yieldfi/index.ts` around lines 121 - 132, The loop currently converts
supplies/rates to Number and uses floating math (loss of precision for 1e18);
change the accumulation to use bigint math: convert s0,s1,r0,r1 from suppliesAt
and ratesAt into BigInt, compute avgSupply = (s0 + s1) / 2n and rateDelta = r1 -
r0 as BigInt, then perform all scaling with BigInt power expressions (e.g., 10n
** BigInt(decimals[i]) and 10n ** BigInt(decimals[i] - assetDecimals[i])) to
compute acc as a BigInt; only convert to the expected type when calling
dailyFees.add (or adjust dailyFees.add to accept BigInt) and use acc !== 0n for
the nonzero check. Ensure you reference YIELD_SEGMENTS, suppliesAt, ratesAt,
decimals, assetDecimals, acc, and dailyFees.add when applying the change.
| cacheInCloud: true, | ||
| fromBlock, | ||
| }); | ||
| const vaultDeployedLogs = await fetchVaultDeployedLogs(options, vaultDeployer); |
There was a problem hiding this comment.
vauluDeployer was deployed 75 days ago, what do you intend to do by using fromBlock which is a year and half old
| const toFeeBlock = await options.getToBlock(); | ||
| const feeSpan = toFeeBlock - fromFeeBlock; | ||
| const boundaryBlocks: number[] = []; | ||
| for (let j = 0; j <= YIELD_SEGMENTS; j++) { |
There was a problem hiding this comment.
pull hourly fetches blocks every hour, so i dont think you need to split again to calculate every 6 minutes
Summary by CodeRabbit
Release Notes
Refactor