-
Notifications
You must be signed in to change notification settings - Fork 93
Description
Overview
Currently, eth_gasPrice does not use caching (removed in hotfix #4583). This was necessary because the previous 15-minute cache TTL was misaligned with Hedera's hourly gas price updates, causing stale values to be returned to clients like MetaMask.
Network fees from the Mirror Node change on clock hour boundaries (e.g., 13:00:00, 14:00:00). To optimize performance while maintaining accuracy, we need a caching strategy that aligns cache expiration with these hourly boundaries.
Proposed Solution
Implement dynamic TTL caching that expires gas prices at the next hour boundary plus a small buffer:
-
Calculate expiration time: When
eth_gasPriceis called, calculate TTL as the time remaining until the next clock hour + buffer seconds- Example: Request at
13:59:00→ cache until14:00:0x(wherexis buffer, e.g., 1-3 seconds) - Example: Request at
14:01:00→ cache until15:00:0x
- Example: Request at
-
Implementation approach:
- Modify the
gasPrice()method inCommonServiceto use a custom caching strategy - Calculate dynamic TTL:
ttl = (3600 - (currentTimeSeconds % 3600)) + bufferSeconds - Apply cache with the calculated TTL instead of a fixed duration
- Modify the
-
Clock drift buffer: Add a configurable buffer (default 1-3 seconds) to account for potential clock drift between servers
Considerations
Critical Edge Case: Cache Miss After Hour Boundary
Problem: On cache miss at 14:00:01, if Mirror Node hasn't updated yet, the relay caches the old price with TTL of ~1 hour, recreating the original hotfix bug. This only affects the first request after hour boundaries, but impact is severe (full hour of stale data causing transaction failures).
Note: Cache hits are unaffected—old values expire within x buffer seconds as designed.
Recommended Fix: Implement minimum TTL threshold (X seconds). Skip caching if calculated_ttl > 3600 - threshold, forcing fresh fetch during Mirror Node update windows while maintaining performance for remaining ~59 minutes.
Example:
const MIN_CACHE_THRESHOLD = X; // x seconds (TBD)
const timeUntilNextHour = 3600 - (currentSeconds % 3600);
const calculatedTTL = timeUntilNextHour + bufferSeconds;
if (calculatedTTL > 3600 - MIN_CACHE_THRESHOLD) {
// Within X after hour boundary (14:00:00 - 14:00:0X)
// Don't cache, return fresh value directly
// Ensure we fetch latest from Mirror Node during this "danger window"
return await fetchFromMirrorNode();
}
// Safe to cache for remaining time
return await cacheWithTTL(calculatedTTL);Related Issues
Follow-up to hotfix #4583 which removed caching to resolve MetaMask failures