Lucene search

K
code423n4Code4renaCODE423N4:2023-06-LLAMA-FINDINGS-ISSUES-292
HistoryJun 14, 2023 - 12:00 a.m.

NATIVE TOKENS TRANSFERRED TO THE LlamaAccount CONTRACT CAN GET STUCK

2023-06-1400:00:00
Code4rena
github.com
1
llamaaccount
stuck tokens
recovery function
llamaexecutor
receive function
eth-transfer

Lines of code
<https://github.com/code-423n4/2023-06-llama/blob/main/src/accounts/LlamaAccount.sol#L147-L150&gt;
<https://github.com/code-423n4/2023-06-llama/blob/main/src/LlamaExecutor.sol#L29-L36&gt;
<https://github.com/code-423n4/2023-06-llama/blob/main/src/LlamaCore.sol#L333-L334&gt;

Vulnerability details

Impact

In the LlamaAccount contract there is a payable recieve() to receive native tokens as shown below:

receive() external payable {}

Hence this contrat accepts native tokens sent to this. But the problem is if any amount of native token is sent to this contract via an external call by mistake it will get stuck for ever since there is no recovery function in the contract.

The only function to retrieve the native tokens is the LlamaAccount.transferNativeToken(). But this function is called by the LlamaExecutor.execute() function which in turn is called by the LlamaCore.executeAction() function as follows:

(bool success, bytes memory result) =
  executor.execute(actionInfo.target, actionInfo.value, action.isScript, actionInfo.data);

As it is shown in the above code snippet the amount of native token to be withdrawn is given in actionInfo.value. It should be same as the msg.value passed into that payable function.

Hence one will not be able to retrieve the stucked native eth in the Llamacontract by calling the LlamaAccount.transferNativeToken().

Proof of Concept

  receive() external payable {}

<https://github.com/code-423n4/2023-06-llama/blob/main/src/accounts/LlamaAccount.sol#L143&gt;

  function transferNativeToken(NativeTokenData calldata nativeTokenData) public onlyLlama {
    if (nativeTokenData.recipient == address(0)) revert ZeroAddressNotAllowed();
    nativeTokenData.recipient.sendValue(nativeTokenData.amount);
  }

<https://github.com/code-423n4/2023-06-llama/blob/main/src/accounts/LlamaAccount.sol#L147-L150&gt;

  function execute(address target, uint256 value, bool isScript, bytes calldata data)
    external
    returns (bool success, bytes memory result)
  {
    if (msg.sender != LLAMA_CORE) revert OnlyLlamaCore();
    (success, result) = isScript ? target.delegatecall(data) : target.call{value: value}(data);
  }
}

<https://github.com/code-423n4/2023-06-llama/blob/main/src/LlamaExecutor.sol#L29-L36&gt;

    (bool success, bytes memory result) =
      executor.execute(actionInfo.target, actionInfo.value, action.isScript, actionInfo.data);

<https://github.com/code-423n4/2023-06-llama/blob/main/src/LlamaCore.sol#L333-L334&gt;

Tools Used

Manual Review and VSCode

Recommended Mitigation Steps

Hence it is recommended to implement a recovery function in the LlamaAccount contract, to recover the which is only callable by the owner (LlamaExecutor) of the contract, to withdraw any stuck native tokens to a separate address.

This is because the LlamaAccount contract has receive() external payable {} function implemented.

Assessed type

ETH-Transfer


The text was updated successfully, but these errors were encountered:

All reactions