Missing return statement will make mtOFT's compose calls of message type MSG_XCHAIN_LEND_XCHAIN_LOCK always fail
Summary
Missing a return statement when executing compose calls of type MSG_XCHAIN_LEND_XCHAIN_LOCK will lead to the call always failing, preventing these type of calls from ever taking place.
Vulnerability Detail
When a compose message is received in an mtOFT token, TapiocaOmnichainReceiver’s _lzCompose() function will be executed. This function will handle different kinds of msgType, prioritizing MSG_REMOTE_TRANSFER and the messages checked inside _extExec():
// TapiocaOmnichainReceive.sol
function _lzCompose(address srcChainSender_, bytes32 _guid, bytes memory oftComposeMsg_) internal {
// Decode OFT compose message.
(uint16 msgType_,,, bytes memory tapComposeMsg_, bytes memory nextMsg_) =
TapiocaOmnichainEngineCodec.decodeToeComposeMsg(oftComposeMsg_);
// Call Permits/approvals if the msg type is a permit/approval.
// If the msg type is not a permit/approval, it will call the other receivers.
if (msgType_ == MSG_REMOTE_TRANSFER) {
_remoteTransferReceiver(srcChainSender_, tapComposeMsg_);
} else if (!_extExec(msgType_, tapComposeMsg_)) {
...
} else {
// If no TOE extender is set or msg type doesn't match extender, try to call the internal receiver.
if (!_toeComposeReceiver(msgType_, srcChainSender_, tapComposeMsg_)) {
revert InvalidMsgType(msgType_);
}
}
}
emit ComposeReceived(msgType_, _guid, tapComposeMsg_);
if (nextMsg_.length > 0) {
_lzCompose(address(this), _guid, nextMsg_);
}
}
As the code snippet shows, the last message type check and execution will be performed inside the _toeComposeReceiver(), which contains message type checks specific to the token (in this case, the mtOFT). The _toeComposeReceiver() implementation can be found inside BaseTOFTReceiver.sol. This function will check another set of message types (hidden in the … in the next code snippet for simplicity), and if no message type is found, then a final _toftCustomComposeReceiver() will be called.
The issue with this function is that when _msgType is of type MSG_XCHAIN_LEND_XCHAIN_LOCK , a return value of true should be sent, but as the code snippet shows, nothing is returned instead. This will make a false success value be returned due to Solidity defaulting booleans to false.
Because a false return value is sent (even if the message type is correct), the if condition performed inside the _lzCompose() which checks whether _toeComposeReceiver() returns a false value will evaluate to true, making messages of type MSG_XCHAIN_LEND_XCHAIN_LOCK always revert with an invalid InvalidMsgType() error.
Impact
High. One of mtOFT ’s core functionalities is broken, making it impossible to execute compose calls that trigger the TOFTOptionsReceiver module mintLendXChainSGLXChainLockAndParticipateReceiver() function.
0xadrii
high
Missing return statement will make mtOFT's compose calls of message type MSG_XCHAIN_LEND_XCHAIN_LOCK always fail
Summary
Missing a return statement when executing compose calls of type MSG_XCHAIN_LEND_XCHAIN_LOCK will lead to the call always failing, preventing these type of calls from ever taking place.
Vulnerability Detail
When a compose message is received in an
mtOFT
token,TapiocaOmnichainReceiver
’s_lzCompose()
function will be executed. This function will handle different kinds ofmsgType
, prioritizingMSG_REMOTE_TRANSFER
and the messages checked inside_extExec()
:As the code snippet shows, the last message type check and execution will be performed inside the
_toeComposeReceiver()
, which contains message type checks specific to the token (in this case, themtOFT
). The_toeComposeReceiver()
implementation can be found insideBaseTOFTReceiver.sol
. This function will check another set of message types (hidden in the … in the next code snippet for simplicity), and if no message type is found, then a final_toftCustomComposeReceiver()
will be called.For
mtOFTs
, the_toftCustomComposeReceiver()
is implemented inmtOFTReceiver.sol
:The issue with this function is that when
_msgType
is of typeMSG_XCHAIN_LEND_XCHAIN_LOCK
, a return value oftrue
should be sent, but as the code snippet shows, nothing is returned instead. This will make afalse
success value be returned due to Solidity defaulting booleans to false.Because a
false
return value is sent (even if the message type is correct), the if condition performed inside the_lzCompose()
which checks whether_toeComposeReceiver()
returns a false value will evaluate to true, making messages of typeMSG_XCHAIN_LEND_XCHAIN_LOCK
always revert with an invalidInvalidMsgType()
error.Impact
High. One of mtOFT ’s core functionalities is broken, making it impossible to execute compose calls that trigger the TOFTOptionsReceiver module mintLendXChainSGLXChainLockAndParticipateReceiver() function.
Code Snippet
https://github.com/sherlock-audit/2024-02-tapioca/blob/main/TapiocaZ/contracts/tOFT/modules/mTOFTReceiver.sol#L43
Tool used
Manual Review
Recommendation
Return a
true
value inside_toftCustomComposeReceiver()
when message is of typeMSG_XCHAIN_LEND_XCHAIN_LOCK
:Duplicate of #63