Maia DAO Ecosystem - Emmanuel's results

Efficient liquidity renting and management across chains with Curvenized Uniswap V3.

General Information

Platform: Code4rena

Start Date: 30/05/2023

Pot Size: $300,500 USDC

Total HM: 79

Participants: 101

Period: about 1 month

Judge: Trust

Total Solo HM: 36

Id: 242

League: ETH

Maia DAO Ecosystem

Findings Distribution

Researcher Performance

Rank: 9/101

Findings: 5

Award: $9,112.31

🌟 Selected for report: 3

πŸš€ Solo Findings: 1

Findings Information

🌟 Selected for report: Emmanuel

Also found by: xuwinnie

Labels

bug
3 (High Risk)
primary issue
satisfactory
selected for report
sponsor confirmed
H-08

Awards

2568.2552 USDC - $2,568.26

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L433

Vulnerability details

Impact

Attacker will cause user's funds to be collected and locked on Branch chain without it being recorded on root chain.

Proof of Concept

Anyone can call BranchBridgeAgent#retrieveDeposit, with an invalid _depositNonce:

function retrieveDeposit(
        uint32 _depositNonce
    ) external payable lock requiresFallbackGas {
        //Encode Data for cross-chain call.
        bytes memory packedData = abi.encodePacked(
            bytes1(0x08),
            _depositNonce,
            msg.value.toUint128(),
            uint128(0)
        );

        //Update State and Perform Call
        _sendRetrieveOrRetry(packedData);
    }

If for example, global depositNonce is x, attacker can call retrieveDeposit(x+y). RootBridgeAgent#anyExecute will be called, and the executionHistory for the depositNonce that the attacker specified would be updated to true:

    function anyExecute(bytes calldata data){
        ...
    /// DEPOSIT FLAG: 8 (retrieveDeposit)
    else if (flag == 0x08) {
    //Get nonce
    uint32 nonce = uint32(bytes4(data[1:5]));

    //Check if tx has already been executed
    if (!executionHistory[fromChainId][uint32(bytes4(data[1:5]))]) {
        //Toggle Nonce as executed
        executionHistory[fromChainId][nonce] = true;

        //Retry failed fallback
        (success, result) = (false, "");
    } else {
        _forceRevert();
        //Return true to avoid triggering anyFallback in case of `_forceRevert()` failure
        return (true, "already executed tx");
    }
    }
    ...
    }

This means that when a user makes a deposit on that BranchBridgeAgent and his Deposit gets assigned a depositNonce which attacker previously called retrieveDeposit for, his tokens would be collected on that BranchBridgeAgent, but would not succeed on RootBridgeAgent because executionHistory for that depositNonce has already been maliciously set to true.

Attack Scenario

  • current global deposit nonce is 50
  • attacker calls retrieveDeposit(60), which would update executionHistory of depositNonce 60 to true on Root chain
  • when a user tries to call any of the functions(say callOutAndBridge), and gets assigned depositNonce of 60, it won't be executed on root chain because executionHistory for depositNonce 60 is already set to true
  • User won't also be able to claim his tokens because anyFallback was not triggered. So he has lost his deposit.

Tools Used

Manual Review

A very simple and effective solution is to ensure that in the BranchBridgeAgent#retrieveDepoit function, msg.sender==getDeposit[_depositNonce].owner just like it was done in BranchBridgeAgent#retryDeposit

Assessed type

Invalid Validation

#0 - c4-judge

2023-07-11T10:39:39Z

trust1995 marked the issue as primary issue

#1 - c4-judge

2023-07-11T10:39:44Z

trust1995 marked the issue as satisfactory

#2 - c4-sponsor

2023-07-12T16:27:20Z

0xBugsy marked the issue as sponsor confirmed

#3 - c4-judge

2023-07-25T13:07:05Z

trust1995 marked the issue as selected for report

#4 - 0xLightt

2023-09-06T17:28:32Z

Findings Information

🌟 Selected for report: Emmanuel

Also found by: xuwinnie

Labels

bug
3 (High Risk)
primary issue
satisfactory
selected for report
sponsor confirmed
H-09

Awards

2568.2552 USDC - $2,568.26

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L58

Vulnerability details

Impact

A malicious user would make a deposit specifying an hToken of a high value(say hEther), and a depositToken of relatively lower value(say USDC), and for that user, RootBridgeAgent would increment his hToken balance by the amount of depositTokens he sent

Proof of Concept

Here is the checkParams function:

function checkParams(address _localPortAddress, DepositParams memory _dParams, uint24 _fromChain)
        internal
        view
        returns (bool)
    {
        if (
            (_dParams.amount < _dParams.deposit) //Deposit can't be greater than amount.
                || (_dParams.amount > 0 && !IPort(_localPortAddress).isLocalToken(_dParams.hToken, _fromChain)) //Check local exists.
                || (_dParams.deposit > 0 && !IPort(_localPortAddress).isUnderlyingToken(_dParams.token, _fromChain)) //Check underlying exists.
        ) {
            return false;
        }
        return true;
    }

The function performs 3 checks:

  • _dParams.amount must be less than or equal to _dParams.deposit
  • If _dParams.amount>0, _dParams.hToken must be a valid localToken
  • If _dParams.deposit>0, _dParams.token must be a valid underlying token.

The PROBLEM is that the check only requires that getLocalTokenFromUnder[_dParams.token]!=address(0), but does not check that getLocalTokenFromUnder[_dParams.token]==_dParams.hToken:

    function isUnderlyingToken(
        address _underlyingToken,
        uint24 _fromChain
    ) external view returns (bool) {
        return
            getLocalTokenFromUnder[_underlyingToken][_fromChain] != address(0);
    }

The checkParams function is used in the RootBridgeAgent#bridgeIn function.

This allows a user to call BranchBridgeAgent#callOutAndBridge with a hToken and token that are not related

ATTACK SCENARIO

  • Current price of Ether is 1800USDC
  • RootBridgeAgent is deployed on Arbitrum
  • BranchBridgeAgent for Ethereum mainnet has two local tokens recorded in RootBridgeAgent:
    • hEther(whose underlying is Ether)
    • hUSDC(whose underlying is USDC)
  • Alice calls BranchBridgeAgent#callOutAndBridge on ethereum with the following as DepositInput(_dParams):
    • hToken(address of local hEther)
    • token(address of USDC)
    • amount(0)
    • deposit(10)
    • toChain(42161)
  • BranchPort#bridgeOut transfers 10 USDC from user to BranchPort, and anyCall call is made to RootBridgeAgent
  • RootBridgeAgent#bridgeIn is called which calls CheckParamsLib.checkParams
    • checkParams verifies that _dParams.amount(0) is less than or equal to _dParams.deposit(10)βœ…
    • verifies that _dParams.hToken(hEther) is a valid localTokenβœ…
    • verifies that _dParams.token(USDC) is a valid underlying token(i.e. its local token is non zero)βœ…
  • RootBridgeAgent#bridgeIn calls RootPort#bridgeToRoot which mints 10 global hEther to user if (_deposit > 0) mint(_recipient, _hToken, _deposit, _fromChainId);
  • With just 10 USDC, user has been able to get 10 ether(18000USDC) worth of funds on root chain.

Execution flow: BranchBridgeAgent#callOutAndBridge->BranchBridgeAgent#_callOutAndBridge->BranchBridgeAgent#_depositAndCall->BranchBridgeAgent#_performCall->RootBridgeAgent#anyExecute->RootBridgeAgentExecutor#executeWithDeposit->RootBridgeAgentExecutor#_bridgeIn->RootBridgeAgent#bridgeIn

Tools Used

Manual Review

Currently, the protocol only checks if the token is recognized by rootport as an underlying token by checking that the registered local token for _dParams.token is not zero address.

  • Instead of that, it would be more effective to check that the registered local token for _dParams.token is equal to _dParams.hToken.
  • Some sanity checks may also be done on DepositInput(_dParams) in BranchBridgeAgent. Although this is not necessary.

Assessed type

Invalid Validation

#0 - c4-judge

2023-07-11T10:38:14Z

trust1995 marked the issue as duplicate of #285

#1 - c4-judge

2023-07-11T10:38:21Z

trust1995 marked the issue as satisfactory

#2 - c4-judge

2023-07-25T13:38:31Z

trust1995 marked the issue as selected for report

#3 - trust1995

2023-07-25T13:38:43Z

Better POC

#4 - 0xBugsy

2023-07-25T18:09:22Z

@trust1995 Same as #273

#5 - c4-sponsor

2023-07-25T18:09:26Z

0xBugsy marked the issue as sponsor confirmed

#6 - c4-judge

2023-07-26T09:22:11Z

trust1995 marked the issue as duplicate of #273

#7 - c4-judge

2023-07-31T14:34:43Z

trust1995 marked the issue as not a duplicate

#8 - c4-judge

2023-07-31T14:34:49Z

trust1995 marked the issue as primary issue

#9 - 0xLightt

2023-09-06T17:30:42Z

Findings Information

🌟 Selected for report: peakbolt

Also found by: Emmanuel, Evo, Noro, zzebra83

Labels

bug
3 (High Risk)
partial-50
upgraded by judge
duplicate-356

Awards

288.0397 USDC - $288.04

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L433-L439 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1243-L1306

Vulnerability details

Impact

There is a function retrieveDeposit in BranchBridgeAgent. But this function is totally unusable and does not serve its intended purpose because there was an omission in implementing its logic.

Proof of Concept

retrieveDeposit attaches a 0x08 flag:

    function retrieveDeposit(uint32 _depositNonce) external payable lock requiresFallbackGas {
        //Encode Data for cross-chain call.
        bytes memory packedData = abi.encodePacked(bytes1(0x08), _depositNonce, msg.value.toUint128(), uint128(0));

        //Update State and Perform Call
        _sendRetrieveOrRetry(packedData);
    }

For the 0x08 flag in RootBridgeAgent#anyExecute, function doesn't do anything on Root chain even when depositNonce is valid, but simply returns a "false" success value to trigger BranchBridgeAgent#anyFallback:

else if (flag == 0x08) {
    //Get nonce
    uint32 nonce = uint32(bytes4(data[1:5]));

    //Check if tx has already been executed
    if (!executionHistory[fromChainId][uint32(bytes4(data[1:5]))]) {
        //Toggle Nonce as executed
        executionHistory[fromChainId][nonce] = true;

        //Retry failed fallback
        (success, result) = (false, "");
    } else {
        _forceRevert();
        //Return true to avoid triggering anyFallback in case of `_forceRevert()` failure
        return (true, "already executed tx");
    }

    //Unrecognized Function Selector
}

But if you check all if statements in BranchBridgeAgent#anyFallback, there is no code that handles 0x08 flag. https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1243-L1306 Therfore, the call would return (false, "unknown selector");, meaning that retrieveDeposit is unusable.

Tools Used

Manual Review

According to the sponsor, it was an omission. In BranchBridgeAgent#anyFallback, instead of if ((flag == 0x00) || (flag == 0x01) || (flag == 0x02)), it should be if ((flag == 0x00) || (flag == 0x01) || (flag == 0x02) || (flag == 0x08))

Assessed type

Error

#0 - c4-judge

2023-07-11T10:27:16Z

trust1995 marked the issue as duplicate of #356

#1 - c4-judge

2023-07-11T10:27:21Z

trust1995 marked the issue as satisfactory

#2 - c4-judge

2023-07-27T14:47:53Z

trust1995 changed the severity to 3 (High Risk)

#3 - c4-judge

2023-07-28T11:27:21Z

trust1995 marked the issue as partial-50

#4 - trust1995

2023-07-28T11:27:47Z

Partial scoring for finding 1/2 of primary's findings.

Findings Information

🌟 Selected for report: peakbolt

Also found by: Emmanuel

Labels

bug
3 (High Risk)
satisfactory
duplicate-266

Awards

1975.5809 USDC - $1,975.58

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1158 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1182 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/BranchBridgeAgent.sol#L1206

Vulnerability details

Impact

It will be impossible to retry a settlement once it fails on ArbitrumBranchBridgeAgent, which could lead to loss of funds.

Proof of Concept

RootBridgeAgent calls ArbitrumBranchBridgeAgent#anyExecute which would bridge in assets. The execution flow for settlement on a BranchBridgeAgent on a chain apart from Arbitrum, goes as follows:

  • User makes a call on BranchBridgeAgent to withdraw his tokens on RootBridgeAgent by calling one of the functions e.g. callOut
  • User's call is relayed to RootBridgeAgent
  • RootBridgeAgent updates the accounting(reduces global hToken balance in case of a withdraw)
  • RootBridgeAgent informs BranchBridgeAgent of the settlement that was made on root chain, so that branch chain can also update accounting of the recipient. Multichain's anyCall is used to call BranchBridgeAgent, which would call BranchBridgeAgent#anyExecute.
  • If anyExecute reverts or returns a "false" success value, anyFallback would be called on RootBridgeAgent, which would allow user to retry or redeem the settlement.
  • Instead of reverting which may expose some attack vectors, protocol wraps the major deposit interaction in a try-catch block, and return false when an error is caught. The assumption is that multichain would also call anyFallback in RootBridgeAgent when it sees that success value is false.

To the best of my understanding, this assumption is correct if BranchBridgeAgent is not ArbitrumBranchBridgeAgent. But for ArbitrumBranchBridgeAgent, RootBridgeAgent calls ArbitrumBranchBridgeAgent#anyExecute directly, and does not use Multichain's anyCall because both of the contracts are on the same chain. Therefore, returning a "false" success value when RootBridgeAgent calls ArbitrumBranchBridgeAgent will not trigger anyFallback, and users settlement will not be reopened for retrying or redemption.

Tools Used

Manual Review

ArbitrumBranchBridgeAgent should call RootBridgeAgent#anyFallback whenever a settlement is unsuccessful.

Assessed type

Other

#0 - c4-judge

2023-07-11T10:32:08Z

trust1995 marked the issue as unsatisfactory: Insufficient proof

#1 - Emedudu

2023-07-26T13:48:39Z

Please have a look at this @trust1995 , @0xBugsy

#2 - c4-judge

2023-07-26T14:04:14Z

trust1995 marked the issue as satisfactory

#3 - c4-judge

2023-07-26T14:04:27Z

trust1995 marked the issue as duplicate of #266

#4 - c4-judge

2023-07-26T14:04:34Z

trust1995 marked the issue as partial-50

#5 - Emedudu

2023-07-26T14:05:22Z

I don't think this is a duplicate of issue 266 Please have a closer look

#6 - trust1995

2023-07-26T14:32:18Z

Hi, both the sponsor and I are of the opinion it is the same underlying issue.

#7 - c4-judge

2023-07-28T11:48:10Z

trust1995 marked the issue as full credit

#8 - c4-judge

2023-07-31T14:29:13Z

trust1995 marked the issue as satisfactory

Findings Information

🌟 Selected for report: peakbolt

Also found by: Emmanuel

Labels

bug
3 (High Risk)
satisfactory
duplicate-266

Awards

1975.5809 USDC - $1,975.58

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L981 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1005 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1073 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1108 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L1134

Vulnerability details

Impact

This causes loss of users funds because when they deposit on ArbitrumBranchBridgeAgent but the deposit was unsuccessful on RootBridgeAgent, the call will not revert(because of try-catch), but rether, returns a "false" success value, and since multicall is not the one that called anyExecute, returning a "false" success value will not trigger anyFallback(which clears users' deposit for redemption) on ArbitrumBranchBridgeAgent.

Proof of Concept

The execution flow for making a deposit from a BranchBridgeAgent on a chain apart from Arbitrum, to RootBridgeAgent goes as follows:

  • User deposits by calling one of the available functions e.g. callOutAndBridge
  • User's tokens are collected on BranchBridgeAgent
  • Multichain's anyCall is used to initiate the cross chain request
  • Multichain calls anyExecute on the destination contract
  • If anyExecute reverts or returns a "false" success value, anyFallback would be called on source contract, which would allow user to claim their deposits
  • Instead of reverting which may expose some attack vectors, protocol wraps the major deposit interaction in a try-catch block, and return false when an error is caught. The assumption is that multichain would call anyFallback in BranchBridgeAgent when it sees that success value is false.

To the best of my understanding, this assumption is correct if BranchBridgeAgent is not ArbitrumBranchBridgeAgent. But for ArbitrumBranchBridgeAgent, RootBridgeAgent#anyExecute is called directly by ArbitrumBranchBridgeAgent, and does not use Multichain's anyCall because both of the contracts are on the same chain. Therefore, returning a "false" success value when ArbitrumBranchBridgeAgent calls RootBridgeAgent will not trigger anyFallback, and users' deposit will not be cleared, but locked forever.

Tools Used

Manual Review

RootBridgeAgent should call ArbitrumBranchBridgeAgent#anyFallback whenever a deposit from Arbitrum branch was unsuccessful.

Assessed type

Other

#0 - c4-judge

2023-07-11T10:32:37Z

trust1995 marked the issue as unsatisfactory: Insufficient proof

#1 - Emedudu

2023-07-26T05:45:43Z

If a deposit from a branch chain does not get recorded on root chain, Multichain calls anyFallback on the branch chain to allow users to claim their funds ArbitrumBranchBridgeAgent also has an anyFallback function which was inherited from BranchBridgeAgent, but this function will not be called when deposits fail in RootBranchBridgeAgent. The reason for this is that the call does not use Multichain because both ArbitrumBranchBridgeAgent and RootBrigdeAgent are on the same chain. So users that make a deposit through ArbitrumBranchBridgeAgent will not be able to claim their deposits if it fails on RootBridgeAgent. The major operations in RootBridgeAgent#anyExecute is wrapped in a try-catch block, and if there is an error(i.e. a failed deposit), a success value of "false" is returned(instead of reverting). When Multichain sees the "false" return value, it calls anyFallback on the source branch chain to clear the user's deposit. But for ArbitrumBranchBridgeAgent, the "false" return value has no effect because it does not trigger anyFallback and does not revert. Therefore user's deposits from ArbitrumBranchBridgeAgent, which fails on RootBridgeAgent, are lost.

#2 - trust1995

2023-07-26T09:56:09Z

@0xBugsy

#3 - 0xBugsy

2023-07-26T12:56:27Z

If a deposit from a branch chain does not get recorded on root chain, Multichain calls anyFallback on the branch chain to allow users to claim their funds ArbitrumBranchBridgeAgent also has an anyFallback function which was inherited from BranchBridgeAgent, but this function will not be called when deposits fail in RootBranchBridgeAgent. The reason for this is that the call does not use Multichain because both ArbitrumBranchBridgeAgent and RootBrigdeAgent are on the same chain. So users that make a deposit through ArbitrumBranchBridgeAgent will not be able to claim their deposits if it fails on RootBridgeAgent. The major operations in RootBridgeAgent#anyExecute is wrapped in a try-catch block, and if there is an error(i.e. a failed deposit), a success value of "false" is returned(instead of reverting). When Multichain sees the "false" return value, it calls anyFallback on the source branch chain to clear the user's deposit. But for ArbitrumBranchBridgeAgent, the "false" return value has no effect because it does not trigger anyFallback and does not revert. Therefore user's deposits from ArbitrumBranchBridgeAgent, which fails on RootBridgeAgent, are lost.

@trust1995 I believe this is the same as #266, ArbitrumBranchBridgeAgent would have it's anyFallback function called in reaction to a _performCall that failed, due to this we only need to revert execution in such cases since ArbBranch -> Root execution is either started from an EOA or already encapsulated in a try-catch in the Root so reversal is caught and gas properly managed

#4 - c4-judge

2023-07-26T13:22:16Z

trust1995 marked the issue as satisfactory

#5 - c4-judge

2023-07-26T13:22:30Z

trust1995 marked the issue as duplicate of #266

Findings Information

🌟 Selected for report: Emmanuel

Labels

bug
2 (Med Risk)
primary issue
satisfactory
selected for report
sponsor confirmed
M-12

Awards

1712.1701 USDC - $1,712.17

External Links

Lines of code

https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L873-L890 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L922 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L246 https://github.com/code-423n4/2023-05-maia/blob/main/src/ulysses-omnichain/RootBridgeAgent.sol#L571

Vulnerability details

Impact

Wrong userFeeInfo will be used when retrySettlement is called directly.

Proof of Concept

Here is retrySettlement function:

function retrySettlement(
    uint32 _settlementNonce,
    uint128 _remoteExecutionGas
) external payable {
    //Update User Gas available.
    if (initialGas == 0) {
        userFeeInfo.depositedGas = uint128(msg.value);
        userFeeInfo.gasToBridgeOut = _remoteExecutionGas;
    }
    //Clear Settlement with updated gas.
    _retrySettlement(_settlementNonce);
}

The assumption here is that if initialGas is not 0, then retrySettlement is being called by RootBridgeAgent#anyExecute, which has already set values for initialGas and userFeeInfo(which would later be deleted at end of the anycall function), but if it is 0, then retrySettlement is being called directly by a user, so user should specify _remoteExecutionGas and send some msg.value with the call, which would make up the userFeeInfo. But this assumption is not completely correct because whenever RootBridgeAgent#anyExecute is called with a depositNonce that has been recorded in executionHistory, the function returns early, which prevents other parts of the anyExecute function from being executed. At the beginning of anyExecute, initialGas and userFeeInfo values are set and at the end of anyExecute call, if initialGas>0, _payExecutionGas sets initialGas and userFeeInfo to 0. So when the function returns earlier, before _payExecutionGas is called, initialGas and userFeeInfo are not updated. If a user calls retrySettlement immediately after that, the call will use a wrong userFeeInfo(i.e. userFeeInfo set when anyExecute was called with a depositNonce that has already been recorded) because initialGas!=0. Whereas, it was meant to use values sent by caller of retrySettlement

Looking at a part of _manageGasOut logic which is called in _retrySettlement,


if (_initialGas > 0) {
    if (
        userFeeInfo.gasToBridgeOut <= MIN_FALLBACK_RESERVE * tx.gasprice
    ) revert InsufficientGasForFees();
    (amountOut, gasToken) = _gasSwapOut(
        userFeeInfo.gasToBridgeOut,
        _toChain
    );
} else {
    if (msg.value <= MIN_FALLBACK_RESERVE * tx.gasprice)
        revert InsufficientGasForFees();
    wrappedNativeToken.deposit{value: msg.value}();
    (amountOut, gasToken) = _gasSwapOut(msg.value, _toChain);
}

This could cause one of these:

  • User's retrySettlement call would revert if userFeeInfo.gasToBridgeOut(which user does not have control over) is less than MIN_FALLBACK_RESERVE * tx.gasprice
  • User's call passes without him sending any funds, so he makes a free retrySettlement transaction

Tools Used

Manual Review

Consider implementing one of these:

  • restrict retrySettlement to only be called by AgentExecutor
  • or delete initialGas and userFeeInfo before return is called if nonce has been executed before:
//Check if tx has already been executed
if (executionHistory[fromChainId][nonce]) {
    _forceRevert();
    delete initialGas;
    delete userFeeInfo;
    //Return true to avoid triggering anyFallback in case of `_forceRevert()` failure
    return (true, "already executed tx");
}

Assessed type

Error

#0 - c4-judge

2023-07-11T10:29:57Z

trust1995 marked the issue as primary issue

#1 - c4-judge

2023-07-11T10:30:02Z

trust1995 marked the issue as satisfactory

#2 - 0xBugsy

2023-07-12T16:18:23Z

This would be the best route to amend this in our opinion delete initialGas and userFeeInfo before return is called if nonce has been executed before

#3 - c4-sponsor

2023-07-12T16:18:28Z

0xBugsy marked the issue as sponsor confirmed

#4 - c4-judge

2023-07-25T13:07:32Z

trust1995 marked the issue as selected for report

#5 - c4-sponsor

2023-07-27T19:06:40Z

0xBugsy marked the issue as sponsor acknowledged

#6 - c4-sponsor

2023-07-28T16:02:48Z

0xBugsy marked the issue as sponsor confirmed

#7 - 0xBugsy

2023-07-28T16:02:53Z

We recognize the audit's findings on Anycall Gas Management. These will not be rectified due to the upcoming migration of this section to LayerZero.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax Β© 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter