Guardian's review of Console EVM Updates for LayerZero, published July 2026. The report records 4 findings, including 1 low and 3 informational.
- Published
- Review window
- July 16 to 21, 2026
- Language
- Solidity
- Chains
- Ethereum, Solana, Stellar, Canton
- Sector
- Cross-chain
- 0 Critical
- 0 High
- 0 Medium
- 1 Low
- 3 Informational
Scope
67 files in scope · 3,013 nSLOC
| File | nSLOC | Lines |
|---|---|---|
apps/oapp-app/contracts/evm/non-upgradeable-next/contracts/oapp/libs/OptionsBuilder.sol | 74 | 181 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/alt/OAppAltUpgradeable.sol | 20 | 48 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/messaging-channel/OAppMessagingChannelBaseUpgradeable.sol | 19 | 76 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/messaging-channel/OAppMessagingChannelRBACUpgradeable.sol | 27 | 70 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/msg-inspection/OAppMsgInspectionBaseUpgradeable.sol | 26 | 67 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/msg-inspection/OAppMsgInspectionRBACUpgradeable.sol | 11 | 34 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/OAppCoreBaseUpgradeable.sol | 47 | 114 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/OAppCoreRBACUpgradeable.sol | 19 | 71 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/OAppReceiverUpgradeable.sol | 26 | 118 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/OAppSenderUpgradeable.sol | 44 | 130 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/OAppUpgradeable.sol | 12 | 45 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/options-type-3/OAppOptionsType3BaseUpgradeable.sol | 50 | 122 |
apps/oapp-app/contracts/evm/upgradeable-next/contracts/oapp/options-type-3/OAppOptionsType3RBACUpgradeable.sol | 11 | 34 |
apps/oft-app/contracts/evm/non-upgradeable-next/contracts/libs/OFTComposeMsgCodec.sol | 31 | 85 |
apps/oft-app/contracts/evm/non-upgradeable-next/contracts/libs/OFTMsgCodec.sol | 29 | 78 |
apps/oft-app/contracts/evm/non-upgradeable-next/contracts/utils/OFTDecimalUtils.sol | 33 | 88 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/alt/OFTBurnMintExtendedRBACAltUpgradeable.sol | 28 | 52 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/alt/OFTBurnSelfMintExtendedRBACAltUpgradeable.sol | 26 | 50 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/alt/OFTLockUnlockExtendedRBACAltUpgradeable.sol | 14 | 33 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/OFTBurnMintExtendedRBACUpgradeable.sol | 63 | 162 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/OFTBurnSelfMintExtendedRBACUpgradeable.sol | 34 | 77 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/OFTCoreExtendedRBACUpgradeable.sol | 96 | 170 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/OFTLockUnlockExtendedRBACUpgradeable.sol | 43 | 93 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/extended/OFTNativeExtendedRBACUpgradeable.sol | 57 | 134 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/oft/OFTCoreBaseUpgradeable.sol | 122 | 344 |
apps/oft-app/contracts/evm/upgradeable-next/contracts/oft/OFTCoreRBACUpgradeable.sol | 21 | 52 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/alt/OFTBurnMintAlt.sol | 23 | 33 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/alt/OFTBurnSelfMintAlt.sol | 21 | 31 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/alt/OFTLockUnlockAlt.sol | 9 | 19 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/ERC20Plus.sol | 49 | 118 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/OFTBurnMint.sol | 23 | 45 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/OFTBurnSelfMint.sol | 21 | 45 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/OFTLockUnlock.sol | 9 | 19 |
apps/project-types/console-oft-next-app/contracts/evm/contracts/OFTNative.sol | 9 | 19 |
apps/project-types/nexus-next-app/contracts/evm/contracts/extensions/OFTRegistryBaseUpgradeable.sol | 89 | 189 |
apps/project-types/nexus-next-app/contracts/evm/contracts/extensions/OFTRegistryRBACUpgradeable.sol | 16 | 50 |
apps/project-types/nexus-next-app/contracts/evm/contracts/extensions/TokenScalesBaseUpgradeable.sol | 41 | 107 |
apps/project-types/nexus-next-app/contracts/evm/contracts/libs/NexusMsgCodec.sol | 35 | 111 |
apps/project-types/nexus-next-app/contracts/evm/contracts/modules/NexusFeeConfigModule.sol | 83 | 172 |
apps/project-types/nexus-next-app/contracts/evm/contracts/modules/NexusModule.sol | 34 | 92 |
apps/project-types/nexus-next-app/contracts/evm/contracts/modules/NexusPauseModule.sol | 98 | 197 |
apps/project-types/nexus-next-app/contracts/evm/contracts/modules/NexusRateLimiterModule.sol | 54 | 121 |
apps/project-types/nexus-next-app/contracts/evm/contracts/Nexus.sol | 274 | 574 |
apps/project-types/nexus-next-app/contracts/evm/contracts/NexusAlt.sol | 17 | 46 |
apps/project-types/nexus-next-app/contracts/evm/contracts/NexusERC20.sol | 74 | 168 |
apps/project-types/nexus-next-app/contracts/evm/contracts/NexusERC20Guard.sol | 22 | 47 |
apps/project-types/nexus-next-app/contracts/evm/contracts/NexusOFT.sol | 80 | 167 |
apps/project-types/nexus-next-app/contracts/evm/contracts/NexusOFTAlt.sol | 38 | 73 |
apps/proxy-app/contracts/evm/proxy-v5-next-evm/contracts/ProxyAdmin2Step.sol | 17 | 39 |
apps/proxy-app/contracts/evm/proxy-v5-next-evm/contracts/TransparentUpgradeableProxy2Step.sol | 31 | 109 |
contracts/common/utils/evm/upgradeable-next/contracts/access/AccessControl2StepUpgradeable.sol | 68 | 144 |
contracts/common/utils/evm/upgradeable-next/contracts/allowlist/AllowlistBaseUpgradeable.sol | 94 | 184 |
contracts/common/utils/evm/upgradeable-next/contracts/allowlist/AllowlistRBACUpgradeable.sol | 19 | 55 |
contracts/common/utils/evm/upgradeable-next/contracts/credit-redirect/CreditRedirectBaseUpgradeable.sol | 45 | 103 |
contracts/common/utils/evm/upgradeable-next/contracts/credit-redirect/CreditRedirectRBACUpgradeable.sol | 11 | 35 |
contracts/common/utils/evm/upgradeable-next/contracts/fee-accounting/FeeHandlerBaseUpgradeable.sol | 29 | 69 |
contracts/common/utils/evm/upgradeable-next/contracts/fee-accounting/FeeHandlerRBACUpgradeable.sol | 11 | 34 |
contracts/common/utils/evm/upgradeable-next/contracts/fee-config/FeeConfigBaseUpgradeable.sol | 54 | 125 |
contracts/common/utils/evm/upgradeable-next/contracts/fee-config/FeeConfigRBACUpgradeable.sol | 15 | 44 |
contracts/common/utils/evm/upgradeable-next/contracts/libs/EnumerableSetPagination.sol | 36 | 69 |
contracts/common/utils/evm/upgradeable-next/contracts/pause-by-id/PauseByIDBaseUpgradeable.sol | 55 | 127 |
contracts/common/utils/evm/upgradeable-next/contracts/pause-by-id/PauseByIDRBACUpgradeable.sol | 30 | 74 |
contracts/common/utils/evm/upgradeable-next/contracts/pause/PauseBaseUpgradeable.sol | 43 | 107 |
contracts/common/utils/evm/upgradeable-next/contracts/pause/PauseRBACUpgradeable.sol | 16 | 47 |
contracts/common/utils/evm/upgradeable-next/contracts/rate-limiter/libs/RateLimiterUtils.sol | 36 | 70 |
contracts/common/utils/evm/upgradeable-next/contracts/rate-limiter/RateLimiterBaseUpgradeable.sol | 272 | 590 |
contracts/common/utils/evm/upgradeable-next/contracts/rate-limiter/RateLimiterRBACUpgradeable.sol | 29 | 81 |
Findings 4
-
L-01 Low OFT interface ID omits receiver functions Unexpected Behavior Resolved
Description
OAPP_EXTENDED_INTERFACE_IDis intended to flatten the complete OApp interface tree. However, it includestype(IOAppReceiver).interfaceIdwithout separately including its parent,ILayerZeroReceiver. Solidity calculates an interface ID using only functions declared directly by that interface. Consequently,type(IOAppReceiver).interfaceIdincludesisComposeMsgSenderbut excludes the inheritedallowInitializePath,nextNonce, andlzReceivefunctions./// @dev Flatten all leaf interface IDs. bytes4 constant OAPP_EXTENDED_INTERFACE_ID = type(IOAppReceiver).interfaceId ^ type(IOAppMessagingChannel).interfaceId ^ type(IOAppCore).interfaceId ^ type(IOAppOptionsType3).interfaceId ^ type(IOAppMsgInspection).interfaceId;The incomplete OApp ID propagates into
OFT_EXTENDED_INTERFACE_ID. The contract currently returns0x97b6b900, whereas the complete flattened interface ID is0x06fbb406. The difference is exactly the omittedILayerZeroReceiverinterface ID. Integrations that independently calculate the identifier from the complete ABI may reject or misidentify compatible OFT deployments.Recommendation
Include
type(ILayerZeroReceiver).interfaceIdwhen calculatingOAPP_EXTENDED_INTERFACE_ID. -
I-01 Informational Divergent guards can block Nexus credits Unexpected Behavior Acknowledged
Description
Nexus processes inbound transfers for multiple registered tokens using a single global
CreditRedirectStorageconfiguration. However, each registered NexusERC20 stores an independent guard pointer that its administrator can replace throughsetGuard. When an inbound message is executed, Nexus first determines the effective recipient using the global allowlist.if (!_isAllowlisted(_to)) { /// @dev `escrow` is guaranteed to be non-zero here. address escrow = _getCreditRedirectStorage().escrow; emit CreditRedirected(_to, escrow, _amountLD); return escrow; } return _to;If the global allowlist considers the intended recipient eligible,
_redirectCreditreturns the original recipient instead of the escrow address. Next, Nexus invokes the registered NexusERC20’smintfunction. Before minting, NexusERC20 performs another validation using that token’s current guard. If the global allowlist and the token’s current guard contain different policies, the global allowlist may accept a recipient that the token guard rejects. In that case, Nexus does not redirect the credit to escrow because_redirectCreditreturns the original recipient, but the subsequent guard check reverts the mint. Consequently, the sender’s tokens have already been burned on the source chain and remain temporarily unavailable while the destination message is pending.Although the intended deployment uses one shared guard for all Nexus tokens, this relationship is not enforced during token registration, credit redirect configuration, or subsequent guard replacement.
Recommendation
Consider enforcing that Nexus’s credit-redirect allowlist remains compatible with every registered NexusERC20 guard.
-
I-02 Informational Empty init data leaves proxy unprotected Informational Resolved
Description
TransparentUpgradeableProxy2Step forwards the caller-provided initialization data to the inherited ERC1967Proxy constructor. The pinned OpenZeppelin version permits this data to be empty, in which case the implementation is installed without initializing the proxy’s storage. If the implementation exposes an external initializer, it remains callable through the proxy. Because non-admin calls are delegated to the implementation, anyone can invoke the initializer before the legitimate administrator and assign themselves application ownership, roles, or other privileged configuration.
Recommendation
Require the proxy to be initialized atomically during deployment using the expected encoded initializer call. Consider upgrading to OpenZeppelin Contracts v5.6 or later, which rejects empty initialization data by default.
-
I-03 Informational Burn docs omit nonce eligibility Documentation Resolved
Description
The interface describes
burnas removing a verified inbound nonce, implying that any verified packet can be burned with the correct payload hash. However, the Endpoint additionally requires the nonce to be at or belowlazyInboundNonce.if (curPayloadHash == EMPTY_PAYLOAD_HASH || _nonce > lazyInboundNonce[_oapp][_srcEid][_sender]) revert Errors.LZ_InvalidNonce(_nonce);Because verification does not advance
lazyInboundNonce, burning a freshly verified packet will revert while its nonce remains above the lazy checkpoint. The incomplete documentation may cause operators to submit reverting recovery transactions or misunderstand whenburnis applicable.Recommendation
Document that
burnrequires an exact, nonempty stored payload hash and_nonce <= lazyInboundNonce.
No findings match.
More from LayerZero
All 7 reports-
Canton VER Updates
169 findings2 critical · 12 high 169 findings: 2 critical, 12 high, 36 medium, 54 low, 65 informational -
Solana Console
42 findings 42 findings: 6 low, 36 informational -
Solana OApp
54 findings 54 findings: 1 medium, 9 low, 44 informational -
OneSig on Stellar
7 findings 7 findings: 4 low, 3 informational
Put your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.