Fujicracy / fuji-v2

Cross-chain money market aggregator
https://fuji-v2-frontend.vercel.app
15 stars 10 forks source link

Fix Incorrect requesterCallData for Flashloan inside router #409

Closed pedrovalido closed 1 year ago

pedrovalido commented 1 year ago

[H-7] Incorrect handling of requesterCallData for Flashloan action inside _getBeneficiaryFromCalldataof the router

Description

When a Flashloan action is executed, the requesterCallData parameter is extracted from the calldata and passed to the _getBeneficiaryFromCalldata function again. (Decode B in the following code)

function _getBeneficiaryFromCalldata(bytes memory callData)
    internal
    pure
    returns (address beneficiary)
{
    // Decode A
  (Action[] memory actions, bytes[] memory args,) =
      abi.decode(callData, (Action[], bytes[], uint256));
  ------
    } else if (actions[0] == Action.Flashloan) {
            // Decode B
      (,,,, bytes memory requestorCalldata) =
        abi.decode(args[0], (IFlasher, address, uint256, address, bytes));
      beneficiary = _getBeneficiaryFromCalldata(requestorCalldata);
    } 
  --------
}

To decode the requesterCallData into actions and arguments inside this second _getBeneficiaryFromCalldata call, the following encoding would be used at Decoding A.

(Action[] memory actions, bytes[] memory args,) = 
abi.decode(callData, (Action[], bytes[], uint256));

However, the requesterCallData of the Flasher has a different format than (Action[], bytes[], uint256) , it is:

(BaseRouter.xBundle.selector, Actions[], bytes[])

This means that the decoding process would fail at point A, and the router would not be able to bridge calldata with Flashloan as its first position.

This is problematic because having Flashloan as the first action is necessary for some of Fuji's use cases, such as closing a position with Flashloan.

Remediation

Consider refactoring _getBeneficiaryFromCalldata to accommodate the Flashloan action.

One way of doing so is

_crossTransferWithCalldata
         decode calldata into actions and args 
         _getBeneficiaryFromActionsAndArgs

_getBeneficiaryFromActionsAndArgs
(Action[] memory actions, bytes[] memory args)
{
    -- FlashloanCase
      (,,,, bytes memory requestorCalldata) =
        abi.decode(args[0], (IFlasher, address, uint256, address, bytes));

            (, Action[] memory actions, bytes[] memory args) =
      abi.decode(requestorCalldata, (BaseRouter.xBundle.selector, Actions[], bytes[]));
      beneficiary = _getBeneficiaryFromCalldata(actions, args);
    } 
 --------
}