Closed code423n4 closed 1 year ago
trust1995 marked the issue as unsatisfactory: Insufficient proof
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.
@0xBugsy
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
trust1995 marked the issue as satisfactory
trust1995 marked the issue as duplicate of #266
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:
To the best of my understanding, this assumption is correct if
BranchBridgeAgent
is notArbitrumBranchBridgeAgent
. But forArbitrumBranchBridgeAgent
,RootBridgeAgent#anyExecute
is called directly byArbitrumBranchBridgeAgent
, and does not use Multichain's anyCall because both of the contracts are on the same chain. Therefore, returning a "false" success value whenArbitrumBranchBridgeAgent
calls RootBridgeAgent will not triggeranyFallback
, and users' deposit will not be cleared, but locked forever.Tools Used
Manual Review
Recommended Mitigation Steps
RootBridgeAgent
should callArbitrumBranchBridgeAgent#anyFallback
whenever a deposit from Arbitrum branch was unsuccessful.Assessed type
Other