F-2026-0013·missing-lifecycle

No mechanism to deregister or disable token pairs leads to permanent persistence of compromised or deprecated pairs

Fixedbridgecross-chainkey-registrygithub.com/pdxwebdev/yadakeyeventwallet
TL;DR

Once a token pair is registered it cannot be removed, disabled, or replaced. A compromised beacon implementation, deprecated original token, or mistakenly registered pair persists forever and can only be addressed via a full contract upgrade.

Severity
LOW
Impact
HIGH
Likelihood
LOW
Method
MManual review
CAT.
Complexity
LOW
Exploitability
LOW
02Section · Description

Description

Once a token pair is registered via registerKeyPairWithTransfer, it is permanent. There is no function in the Bridge to remove a pair from tokenPairs, remove an entry from supportedOriginalTokens, disable wrap/unwrap for a specific pair, or blacklist a compromised wrapped token.

Additionally, the TokenPairExists check at line 492 prevents re-registration, meaning the owner cannot point an original token to a new wrapped token even if the existing one is compromised:

solidity
if (
tokenPairs[pair.originalToken].wrappedToken
!= address(0)
) {
revert TokenPairExists();
}

This becomes problematic if:

  • A wrapped token's beacon implementation is compromised and all wrapping/unwrapping through that pair should be halted immediately.
  • An original token is deprecated, migrated, or becomes unsafe (e.g., exploited on BSC), yet the Bridge continues supporting operations through the stale pair.
  • A malicious or incorrect pair is registered by mistake. The only recourse is a full contract upgrade.
03Section · Recommendation

Recommendation

Add pair lifecycle management:

solidity
mapping(address => bool) public disabledPairs;
function disableTokenPair(
address token_
) external onlyOwner {
if (tokenPairs[token_].wrappedToken == address(0))
revert TokenPairNotSupported();
disabledPairs[token_] = true;
}
function enableTokenPair(
address token_
) external onlyOwner {
disabledPairs[token_] = false;
}

Then add a check at the start of _handleWrap and _handleUnwrap:

solidity
require(
!disabledPairs[permit.token],
"Token pair disabled"
);
04Section · Resolution

Resolution

YadaCoin, Confirmed. Implemented deregisterTokenPair with swap-and-pop removal from the tokenPairs array, fully removing deprecated or compromised pairs.

Zealynx, Fixed. Verified the deregistration mechanism replaces the initial disable/enable approach, addressing all identified gaps including unwrap bypass, one-directional coverage, and re-registration handling.

Status
Fixed
F-2026-0013

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx