Skip to content
Request an audit

‹ All findings

Using LayerZero for synchronizing global states between two chains may lead to overwriting of global states.

Crit/HighAutonomint·Sherlock · Hedged stablecoin · 4th December 2024CodebaseH-26

Summary

Due to the lack of a locking mechanism and the non-atomic nature of cross-chain operations, global states may be at risk of being overwritten.

Root Cause

https://github.com/sherlock-audit/2024-11-autonomint/blob/main/Blockchain/Blockchian/contracts/Core_logic/GlobalVariables.sol#L43 In both Optimism and Mode, there is a global variable omniChainData, which contains numerous data items as follows:

javascript
struct OmniChainData {
        uint256 normalizedAmount;
        uint256 vaultValue;
        uint256 cdsPoolValue;
        uint256 totalCDSPool;
        uint256 collateralRemainingInWithdraw;
        uint256 collateralValueRemainingInWithdraw;
        uint128 noOfLiquidations;
        uint64 nonce;
        uint64 cdsCount;
        uint256 totalCdsDepositedAmount;
        uint256 totalCdsDepositedAmountWithOptionFees;
        uint256 totalAvailableLiquidationAmount;
        uint256 usdtAmountDepositedTillNow;
        uint256 burnedUSDaInRedeem;
        uint128 lastCumulativeRate;
        uint256 totalVolumeOfBorrowersAmountinWei;
        uint256 totalVolumeOfBorrowersAmountinUSD;
        uint128 noOfBorrowers;
        uint256 totalInterest;
        uint256 abondUSDaPool;
        uint256 collateralProfitsOfLiquidators;
        uint256 usdaGainedFromLiquidation;
        uint256 totalInterestFromLiquidation;
        uint256 interestFromExternalProtocolDuringLiquidation;
        uint256 totalNoOfDepositIndices;
        uint256 totalVolumeOfBorrowersAmountLiquidatedInWei;
        uint128 cumulativeValue; // cumulative value
        bool cumulativeValueSign; // cumulative value sign whether its positive or not negative
        uint256 downsideProtected;
    }

The design of this protocol ensures that any changes to omniChainData on one chain are synchronized to other chains via Layer_Zero.

However, due to the lack of a locking mechanism and the non-atomic nature of cross-chain operations, this could lead to overwriting of global states. The following is a simple explanation using a borrow example:

  1. Alice deposits 1 ETH on Optimism, and almost simultaneously, Bob deposits 100 ETH on the Mode chain.
  2. The totalVolumeOfBorrowersAmountinWei on Optimism becomes 1e18, while on the Mode chain, it becomes 100 * 1e18.
  3. Both Optimism and Mode chains send globalVariables.send to synchronize their local data to the other chain.
  4. As a result, totalVolumeOfBorrowersAmountinWei on Optimism becomes 100 * 1e18, while on the Mode chain, it becomes 1e18.

Both chains now hold incorrect totalVolumeOfBorrowersAmountinWei values. The correct value should be 101 * 1e18.

The fundamental issue is that when Alice deposits on Optimism, the cross-chain synchronization to the Mode chain cannot prevent users from performing nearly simultaneous actions on the Mode chain, leading to overwriting of global states.

Furthermore, there could also be scenarios where a message is successfully sent via Layer_Zero on Optimism but encounters an error when executing receive() on the Mode chain, leading to additional inconsistencies.

Impact

Errors in global accounting data can lead to incorrect calculations in critical system processes.

Mitigation

Modify and improve the relevant data synchronization mechanism.