Silent chain truncation at 1000 entries causes getLatestChainEntry to return stale data with no error indication
_buildChainFromHash allocates a fixed 1000-element array and silently breaks the forward traversal when the index reaches the limit, causing getLatestChainEntry to return log[999] as if it were the latest entry.
Description
_buildChainFromHash allocates a fixed-size array of 1000 elements and
silently breaks the forward traversal when the index reaches the limit:
KeyLogEntry[] memory log = new KeyLogEntry[](1000);// ...if (logIndex >= log.length) {break;}
If a key chain exceeds 1000 entries (~500 pair rotations),
the function returns a truncated array. getLatestChainEntry then returns
log[999], not the actual latest entry, with no revert and no
indication that the data is stale.
Every downstream consumer silently operates on incorrect data:
isValidOwnershipTransfer(line 364) validates against the wrong entry, potentially accepting or rejecting ownership transfers incorrectly.rotateToPublicKeyin Bridge reads the wrongprerotatedKeyHash, transferring Bridge ownership to the wrong address.transferBalanceToLatestKeyin Bridge sends all token balances to an outdated key.registerKeyPairWithTransferin Bridge routes permits to the wrongprerotatedKeyHash.
The failure is completely silent, no revert, no event, no return flag.
The bool return from getLatestChainEntry is true because the array
is non-empty, even though the entry is stale.
While 500 pair rotations is unlikely short-term, the protocol provides no guard against reaching this boundary over its deployment lifetime, and the consequences are catastrophic if it does.
Recommendation
Either revert if the chain exceeds the limit:
if (logIndex >= log.length) {revert("Chain exceeds maximum length");}
…or remove the bounded allocation entirely (preferred, see the O(1) mapping approach in [F-2026-0009]).
Resolution
YadaCoin, Confirmed.
Zealynx, Fixed.

