OverlayerWrapCore tracks cross-chain outflow in totalBridgedOut and updates it in OFT hooks:
_debit(...) adds the burned/sent amount._credit(...) subtracts the received amount.On a fresh destination chain, totalBridgedOut starts at 0. The first inbound credit executes:
totalBridgedOut -= amountReceivedLD;
If amountReceivedLD > 0, this underflows and reverts with panic 0x11.
Because the source-side debit has already happened in the send path, the destination receive fails while source balance is already reduced. This creates a transfer-lock condition in cross-chain flow.
contracts/overlayer/OverlayerWrapCore.sol:62contracts/overlayer/OverlayerWrapCore.sol:63_debit(...) implementation starts at contracts/overlayer/OverlayerWrapCore.sol:510contracts/overlayer/OverlayerWrapCore.sol:527_credit(...) implementation starts at contracts/overlayer/OverlayerWrapCore.sol:537super._credit(...) at contracts/overlayer/OverlayerWrapCore.sol:542contracts/overlayer/OverlayerWrapCore.sol:543contracts/overlayer/OverlayerWrapCore.sol:301contracts/overlayer/OverlayerWrapCore.sol:302onlyHubChain modifier definition at contracts/overlayer/OverlayerWrapCore.sol:77contracts/overlayer/OverlayerWrapCore.sol:358contracts/overlayer/OverlayerWrapCore.sol:377totalSupply() + totalBridgedOut() at contracts/overlayerbacking/AaveHandler.sol:240totalBridgedOut() read at contracts/overlayerbacking/AaveHandler.sol:241OverlayerWrapMock contracts using the same mock LayerZero endpoint.hubChainId: hubChainIdNum + 1 at test/Attack_CrossChainCreditUnderflow.ts:56source.testDebit(...) at test/Attack_CrossChainCreditUnderflow.ts:82source.totalBridgedOut() == bridgeAmount at test/Attack_CrossChainCreditUnderflow.ts:85destination.testCredit(...) at test/Attack_CrossChainCreditUnderflow.ts:90revertedWithPanic(0x11) at test/Attack_CrossChainCreditUnderflow.ts:91CI=1 HARDHAT_DISABLE_TELEMETRY_PROMPT=true npx hardhat test --config hardhat.config.poc.ts test/Attack_CrossChainCreditUnderflow.ts
Attack PoC: Cross-chain credit underflow
✔ burns on source but reverts on first destination credit
1 passing
_debit increments totalBridgedOut at contracts/overlayer/OverlayerWrapCore.sol:527_credit decrements totalBridgedOut at contracts/overlayer/OverlayerWrapCore.sol:543_credit0x11 at test/Attack_CrossChainCreditUnderflow.ts:91OverlayerWrapMock:
testDebit at contracts/test/OverlayerWrapMock.sol:10testCredit at contracts/test/OverlayerWrapMock.sol:19contracts/overlayer/OverlayerWrapCore.sol:510contracts/overlayer/OverlayerWrapCore.sol:527contracts/overlayer/OverlayerWrapCore.sol:537contracts/overlayer/OverlayerWrapCore.sol:542contracts/overlayer/OverlayerWrapCore.sol:543contracts/overlayer/OverlayerWrapCore.sol:301contracts/overlayer/OverlayerWrapCore.sol:302contracts/overlayer/OverlayerWrapCore.sol:358contracts/overlayer/OverlayerWrapCore.sol:377contracts/overlayerbacking/AaveHandler.sol:239contracts/overlayerbacking/AaveHandler.sol:240contracts/overlayerbacking/AaveHandler.sol:241contracts/test/OverlayerWrapMock.sol:10contracts/test/OverlayerWrapMock.sol:19test/Attack_CrossChainCreditUnderflow.ts:56test/Attack_CrossChainCreditUnderflow.ts:62test/Attack_CrossChainCreditUnderflow.ts:82test/Attack_CrossChainCreditUnderflow.ts:85test/Attack_CrossChainCreditUnderflow.ts:90test/Attack_CrossChainCreditUnderflow.ts:91hardhat.config.poc.ts