@@ -253,6 +253,10 @@ pub const FallbackFns = struct {
253253 /// lightweight hook lets the fallback (e.g. WitnessDatabase) record the access for
254254 /// EIP-7928 BAL tracking without performing MPT verification.
255255 notify_storage_read : ? * const fn (* anyopaque , primitives.Address , primitives.StorageKey ) void = null ,
256+ /// Returns true if the address was committed to the permanent access log.
257+ /// Used by BaTracker to distinguish legitimately-accessed nonexistent accounts
258+ /// from those only loaded for OOG gas calculation.
259+ is_tracked_address : ? * const fn (* anyopaque , primitives.Address ) bool = null ,
256260};
257261
258262/// In-memory database implementation.
@@ -263,6 +267,10 @@ pub const InMemoryDB = struct {
263267 block_hashes : std .AutoHashMap (u64 , primitives .Hash ),
264268 /// Optional fallback: called on cache miss for account/storage/code/blockHash.
265269 fallback : ? FallbackFns = null ,
270+ /// Addresses that were explicitly OOG-untracked via untrackAddress().
271+ /// Used by BaTracker.computeHash() to exclude CALL gas-calc phantoms from the BAL.
272+ /// Populated by untrackAddress(); never cleared between transactions (block-scoped).
273+ oog_addresses : std .AutoHashMap (primitives.Address , void ),
266274
267275 const Self = @This ();
268276
@@ -272,6 +280,7 @@ pub const InMemoryDB = struct {
272280 .code = std .AutoHashMap (primitives .Hash , bytecode .Bytecode ).init (allocator ),
273281 .storage_map = std .HashMap (struct { primitives .Address , primitives .StorageKey }, primitives .StorageValue , StorageKeyContext , std .hash_map .default_max_load_percentage ).init (allocator ),
274282 .block_hashes = std .AutoHashMap (u64 , primitives .Hash ).init (allocator ),
283+ .oog_addresses = std .AutoHashMap (primitives .Address , void ).init (allocator ),
275284 };
276285 }
277286
@@ -280,6 +289,7 @@ pub const InMemoryDB = struct {
280289 self .code .deinit ();
281290 self .storage_map .deinit ();
282291 self .block_hashes .deinit ();
292+ self .oog_addresses .deinit ();
283293 }
284294
285295 pub fn basic (self : * Self , address : primitives.Address ) ! ? state.AccountInfo {
@@ -339,12 +349,20 @@ pub const InMemoryDB = struct {
339349 if (self .fallback ) | fb | if (fb .revert_frame ) | f | f (fb .ctx );
340350 }
341351
342- /// Un-record a pending address access in the fallback .
352+ /// Un-record a pending address access.
343353 /// Called when a CALL loaded an address for gas calculation but then went OOG.
354+ /// Marks the address as an OOG phantom so BaTracker can exclude it from the BAL.
344355 pub fn untrackAddress (self : * Self , address : primitives.Address ) void {
356+ self .oog_addresses .put (address , {}) catch {};
345357 if (self .fallback ) | fb | if (fb .untrack_address ) | f | f (fb .ctx , address );
346358 }
347359
360+ /// Returns true if the address was OOG-untracked (loaded only for CALL gas calculation).
361+ /// Used by BaTracker.computeHash() to exclude phantom accounts from the BAL.
362+ pub fn isOogAddress (self : * const Self , address : primitives.Address ) bool {
363+ return self .oog_addresses .contains (address );
364+ }
365+
348366 /// Force-add an address to the current-tx access log regardless of witness state.
349367 /// Called for EIP-7702 delegation targets that execute but are not in the witness.
350368 pub fn forceTrackAddress (self : * Self , address : primitives.Address ) void {
@@ -365,6 +383,14 @@ pub const InMemoryDB = struct {
365383 if (self .fallback ) | fb | if (fb .notify_storage_read ) | f | f (fb .ctx , address , slot );
366384 }
367385
386+ /// Returns true if the address was committed to the permanent access log in the fallback.
387+ /// Used by BaTracker to distinguish legitimately-accessed nonexistent accounts
388+ /// from those only loaded for OOG gas calculation.
389+ pub fn isTrackedAddress (self : * Self , address : primitives.Address ) bool {
390+ if (self .fallback ) | fb | if (fb .is_tracked_address ) | f | return f (fb .ctx , address );
391+ return false ;
392+ }
393+
368394 pub fn basicRef (self : Self , address : primitives.Address ) ! ? state.AccountInfo {
369395 return self .accounts .get (address );
370396 }
0 commit comments