Skip to content

fix(oft-evm-upgradeable): align sharedDecimals mutability with IOFT and OFTCore - #1957

Open
Lesnak1 wants to merge 1 commit into
LayerZero-Labs:mainfrom
Lesnak1:fix/oft-upgradeable-shared-decimals-view
Open

Lesnak1 wants to merge 1 commit into
LayerZero-Labs:mainfrom
Lesnak1:fix/oft-upgradeable-shared-decimals-view

Conversation

@Lesnak1

@Lesnak1 Lesnak1 commented Oct 19, 2026

Copy link
Copy Markdown

What does this PR do?

Aligns the state mutability of sharedDecimals() in OFTCoreUpgradeable from pure to view.

Why is this change needed?

In IOFT.sol, sharedDecimals() is declared as external view returns (uint8). Similarly, in all other implementations across the LayerZero V2 ecosystem:

  • packages/oft-evm/contracts/OFTCore.sol: public view virtual
  • packages/oft-alt-evm/contracts/OFTAltCore.sol: public view virtual
  • packages/oft-alt-evm/contracts/OFTAltCoreUpgradeable.sol: public view virtual
  • packages/layerzero-v2/evm/oapp/contracts/oft/OFTCore.sol: public view virtual

Only packages/oft-evm-upgradeable/contracts/oft/OFTCoreUpgradeable.sol declared sharedDecimals() as pure virtual.

Under Solidity's function overriding rules, an overriding function can only maintain or tighten state mutability (view -> pure), but cannot loosen it (pure -> view). Because OFTCoreUpgradeable declared it as pure virtual, any derived upgradeable contract wishing to override sharedDecimals() by reading state (such as an initialized storage variable or underlying token decimals) failed compilation with:
TypeError: Overriding function is missing "pure" mutability (specified in base contract).

Changing pure to view resolves this asymmetry while remaining 100% backward compatible for all callers and existing pure overrides.

Fixes #1954

How was this tested?

  • Added test_shared_decimals_view() regression test in packages/oft-evm-upgradeable/test/OFT.t.sol asserting sharedDecimals() returns expected values via view calls on OFTUpgradeableMock and OFTAdapterUpgradeableMock.
  • Added changeset for @layerzerolabs/oft-evm-upgradeable.

…nd OFTCore

Align the state mutability of sharedDecimals() in OFTCoreUpgradeable from pure to view.

In the IOFT interface, sharedDecimals() is declared as external view returns (uint8). Similarly, in all other implementations across the LayerZero V2 ecosystem (OFTCore, OFTAltCore, OFTAltCoreUpgradeable), sharedDecimals() is defined as public view virtual.

Because Solidity forbids overriding a pure virtual function with a view function, declaring sharedDecimals() as pure in OFTCoreUpgradeable blocked custom upgradeable implementations from overriding sharedDecimals() to read contract state (e.g. from storage/initializer).

Fixes LayerZero-Labs#1954
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistent "pure" for sharedDecimals does not match similar contracts

1 participant