Platform: Code4rena
Start Date: 22/09/2023
Pot Size: $100,000 USDC
Total HM: 15
Participants: 175
Period: 14 days
Judge: alcueca
Total Solo HM: 4
Id: 287
League: ETH
Rank: 70/175
Findings: 1
Award: $46.91
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: nobody2018
Also found by: 0xStalin, 0xnev, 3docSec, Arz, Koolex, Kow, OMEN, gumgumzum, minhtrng, perseverancesuccess, rvierdiiev, windhustler
46.9091 USDC - $46.91
https://github.com/code-423n4/2023-09-maia/blob/f5ba4de628836b2a29f9b5fff59499690008c463/src/BranchBridgeAgent.sol#L587-L701 https://github.com/code-423n4/2023-09-maia/blob/f5ba4de628836b2a29f9b5fff59499690008c463/src/BranchBridgeAgent.sol#L785-L795 https://github.com/code-423n4/2023-09-maia/blob/f5ba4de628836b2a29f9b5fff59499690008c463/src/BranchBridgeAgent.sol#L730-L753 https://github.com/code-423n4/2023-09-maia/blob/f5ba4de628836b2a29f9b5fff59499690008c463/src/BranchBridgeAgent.sol#L712-L721
PerformFallBack is gonna fail and msg.value will be accumulated in that BranchBridgeAgent and malicious user can take over them
User deposited and When it's not executed ,user want to retrieve and callRetrieveSettlement ,send message to BranchBridgeAgent to retrieveSettlement
//DEPOSIT FLAG: 3 (Retrieve Settlement) } else if (flag == 0x03) { // 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); }
_performFallback is executed ,
function _performFallbackCall(address payable _refundee, uint32 _settlementNonce) internal virtual { //Sends message to LayerZero messaging layer ILayerZeroEndpoint(lzEndpointAddress).send{value: address(this).balance}( rootChainId, rootBridgeAgentPath, abi.encodePacked(bytes1(0x09), _settlementNonce), _refundee, address(0), "" ); }
In _performFallback , ILayerZeroEndpoint.send is likely to revert cause there is lack of payable in _refundee or other reason,If they revert ,msg.value that send from RootBridgeAgent will be acummulated in branchBridgeAgent .Malicious user can drain easily them by calling one of execute function like singleSettlement . balance of that BranchBridgeAgent will be sent to Malicious user .
function _execute(uint256 _settlementNonce, bytes memory _calldata) private { //Update tx state as executed executionState[_settlementNonce] = STATUS_DONE; //Try to execute the remote request (bool success,) = bridgeAgentExecutorAddress.call{value: address(this).balance}(_calldata); // No fallback is requested revert allowing for settlement retry. if (!success) revert ExecutionFailure(); }
user can get gas more than deposited if _performFallBack is failed to execute.
manual view
add payable to _refundee if _performFallback is failed to execute send those gas to somewhere safe.
Payable
#0 - c4-pre-sort
2023-10-10T08:22:01Z
0xA5DF marked the issue as duplicate of #887
#1 - c4-pre-sort
2023-10-15T06:50:13Z
0xA5DF marked the issue as sufficient quality report
#2 - c4-judge
2023-10-25T09:44:20Z
alcueca marked the issue as satisfactory
#3 - c4-judge
2023-10-25T09:45:02Z
alcueca changed the severity to 2 (Med Risk)
#4 - c4-judge
2023-10-25T09:52:37Z
alcueca marked the issue as partial-50
#5 - c4-judge
2023-11-03T10:53:07Z
alcueca marked the issue as duplicate of #518