Assessment reports>Maia DAO Ulysses Protocol>Discussion>Inaccurate status update

Inaccurate status update

The lzReceiveNonBlocking function in the BranchBridgeAgent contract in one of the cases processes the Retrieve Settlement payload data received from the Root chain. If the executionState is STATUS_DONE, the function reverts, indicating that the settlement has already been successfully executed. In contrast, if the executionState[nonce] is STATUS_READY, it updates the state to STATUS_RETRIEVE. The function then performs a fallback call to the Root chain.

However, the executionState mapping stores uint256 values, theoretically allowing for states beyond the predefined STATUS_READY, STATUS_DONE, and STATUS_RETRIEVE. Therefore, if the current status is not STATUS_READY, the executionState[nonce] will remain unchanged. This means that the function does not guarantee the state to be STATUS_RETRIEVE in such cases, leaving room for additional states within the executionState mapping. Therefore, we recommend checking that the status is set to expected STATUS_RETRIEVE before performing the fallback call.

mapping(uint256 settlementNonce => uint256 state) public executionState;

function lzReceiveNonBlocking(
    address _endpoint,
    uint16 _srcChainId,
    bytes calldata _srcAddress,
    bytes calldata _payload
) public payable override requiresEndpoint(_srcChainId, _endpoint, _srcAddress) {
    //Save Action Flag
    bytes1 flag = _payload[0] & 0x7F;

    // Save settlement nonce
    uint32 nonce;
    ...
    //DEPOSIT FLAG: 4 (Retrieve Settlement)
        } else if (flag == 0x04) {
            // Parse recipient
            address payable recipient = payable(address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED]))));
            //Get nonce
            nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));
            //Check if settlement is in retrieve mode
            if (executionState[nonce] == STATUS_DONE) {
                revert AlreadyExecutedTransaction();
            } else {
                //Set settlement to retrieve mode, if not already set.
                if (executionState[nonce] == STATUS_READY) executionState[nonce] = STATUS_RETRIEVE;
                //Trigger fallback/Retry failed fallback 
                _performFallbackCall(recipient, nonce);
            }
}
Zellic © 2024Back to top ↑