What Is the Vulnerability?
Missing Validation in _credit() Function
The _credit() function in OverlayerWrapCore.sol subtracts from totalBridgedOut without checking if the value is sufficient. While Solidity 0.8+ prevents silent underflow by reverting, the missing validation creates an accounting desync risk if the bridge ever calls _credit without a matching _debit.
Step 1: Locate the Vulnerable Function
File: contracts/overlayer/OverlayerWrapCore.sol Lines: 537–544 solidity
function credit( address to, uint256 amountLD_, uint32 srcEid_ ) internal virtual override returns (uint256 amountReceivedLD) { amountReceivedLD = super.credit(to, amountLD_, srcEid_); totalBridgedOut -= amountReceivedLD; // ❌ Missing validation }
Screenshot: (Attach screenshot of the code) Step 2: Understand the Normal Flow
In normal OFT bridge operation: Event Action totalBridgedOut User sends cross-chain _debit() called += amount User receives on destination _credit() called -= amount
Result: totalBridgedOut returns to original value. Accounting remains consistent. Step 3: Trigger the Vulnerability
If _credit() is called without a prior _debit(), the subtraction fails:
Scenario:
Assume totalBridgedOut = 0
Bridge calls _credit(user, 100, srcEid)
solidity
// Execution: amountReceivedLD = super._credit(...); // Returns 100 totalBridgedOut -= 100; // ❌ 0 - 100 = underflow
Result: Transaction reverts in Solidity 0.8+. Step 4: Observe the Revert
Screenshot: (Attach screenshot of the revert in a test environment)
Example revert message (from test deployment): text
revert: arithmetic underflow or overflow
Step 5: Impact on AaveHandler
AaveHandler.sol uses totalBridgedOut to calculate collateral:
File: contracts/overlayerbacking/AaveHandler.sol Lines: 239–241 solidity
// Add totalBridgedOut to compensate for OFT cross-chain burns uint256 owTotalSupp = IOverlayerWrap(overlayerWrap).totalSupply() + IOverlayerWrap(overlayerWrap).totalBridgedOut();
If _credit reverts due to underflow, the bridge message fails. If the bridge state becomes desynchronized, totalBridgedOut may be incorrect, affecting collateral calculations. Step 6: Proof of Concept (Simulated)
In a test environment, simulate a _credit call without matching _debit: solidity
// Deploy the contract OverlayerWrapCore core = new OverlayerWrapCore(...);
// Force totalBridgedOut to 0 (initial state) assert(core.totalBridgedOut() == 0);
// Attempt to call _credit (internal, but we can use test wrapper) // This would revert with underflow try core.testCredit(user, 100, srcEid) { // This line should never execute assert(false); } catch { // ✅ Correct behavior — revert }
Screenshot: (Attach screenshot of test execution showing revert) Step 7: Why This Matters Scenario Impact Bridge message replay _credit called twice → underflow → revert Bridge misrouting _credit without _debit → revert → funds stuck Bridge accounting bug totalBridgedOut desync → collateral math wrong Step 8: Recommended Fix
Add a validation check: solidity
function credit(...) internal override returns (uint256 amountReceivedLD) { amountReceivedLD = super.credit(to, amountLD, srcEid_); require(totalBridgedOut >= amountReceivedLD, "Insufficient bridged out balance"); totalBridgedOut -= amountReceivedLD; }