The _credit() function in OverlayerWrapCore.sol (line 543) performs an
unconditional subtraction totalBridgedOut -= amountReceivedLD on every
chain where the contract is deployed. On non-hub chains, totalBridgedOut
is initialized to 0 and can never be incremented because:
(a) _debit() (the only increment path) requires tokens to exist on the
chain to burn them
(b) mint() is restricted to the hub chain via onlyHubChain modifier
(c) _credit() (the only way to receive tokens) always reverts due to
this underflow
This creates an unbreakable deadlock. When a user bridges tokens from the
hub chain via LayerZero OFT send():
_debit() burns the user's tokens (irreversible)_credit() reverts with arithmetic underflowThe contract is not upgradeable and totalBridgedOut has no setter
function, so this cannot be fixed post-deployment.
Root cause:
commit f55efce (March 6, 2026) added totalBridgedOut tracking
to fix a backing contract underflow, but applied the _credit decrement on
ALL chains instead of only the hub chain where it's needed.
Step 1: Clone the repo at the in-scope commit
git clone https://github.com/Overlayerfi/contracts.git
cd contracts
git checkout 519c9e92fd9d80d11e35e9868130f6334b88d676
Step 2: Install dependencies
npm install --force
Step 3: Add the mock endpoint contract
Create contracts/test/MockLzEndpoint.sol with:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract MockLzEndpoint {
mapping(address => address) public delegates;
function setDelegate(address _delegate) external {
delegates[msg.sender] = _delegate;
}
function eid() external pure returns (uint32) {
return 30101;
}
}
Step 4: Create hardhat.config.poc.ts (no fork needed)
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "@nomicfoundation/hardhat-ethers";
import "@nomicfoundation/hardhat-chai-matchers";
const config: HardhatUserConfig = {
solidity: { compilers: [
{ version: "0.8.20", settings: { optimizer: { enabled: true, runs: 300 } } },
{ version: "0.8.10", settings: { optimizer: { enabled: true, runs: 999 } } },
{ version: "0.7.6", settings: { optimizer: { enabled: true, runs: 1000000 },
metadata: { bytecodeHash: "none" } } }
]},
networks: { hardhat: { allowUnlimitedContractSize: true, chainId: 31337 } },
};
export default config;
Step 5: Add the PoC test file test/CreditUnderflow.ts
(attached as file — 3 tests demonstrating underflow, fund loss,
and deadlock)
Step 6: Compile and run
npx hardhat compile --config hardhat.config.poc.ts
npx hardhat test test/CreditUnderflow.ts --config hardhat.config.poc.ts
Step 7: Verify output — all 3 tests pass:
✔ _credit reverts with arithmetic underflow on non-hub chain
(totalBridgedOut == 0)
✔ _debit works on hub chain but tokens are lost because _credit
always fails on destination
✔ non-hub chain can NEVER have totalBridgedOut > 0 —
chicken-and-egg deadlock
Step 8: Verify the root cause at OverlayerWrapCore.sol:543
totalBridgedOut -= amountReceivedLD;
This line has no hub chain guard. On non-hub chains where
totalBridgedOut == 0, any positive amountReceivedLD causes
arithmetic underflow (panic 0x11).