TempleGold

TempleDAO
Foundry
25,000 USDC
View results
Submission Details
Severity: low
Valid

Layerzero miscalculates gas, risking loss of assets

Summary

The mismatch between lzsend and quote functions mean gas will be erroneous which means more gas will be sent or less gas will be sent. In the case of less gas, it means the asset on the destination chain will be stuck

Vulnerability Details

function send(
SendParam calldata _sendParam,
MessagingFee calldata _fee,
address _refundAddress
) external payable virtual override(IOFT, OFTCore) returns (MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) {
if (_sendParam.composeMsg.length > 0) { revert CannotCompose(); }
/// cast bytes32 to address
address _to = _sendParam.to.bytes32ToAddress();
/// @dev user can cross-chain transfer to self
if (msg.sender != _to) { revert ITempleGold.NonTransferrable(msg.sender, _to); }
// @dev Applies the token transfers regarding this send() operation.
// - amountSentLD is the amount in local decimals that was ACTUALLY sent/debited from the sender.
// - amountReceivedLD is the amount in local decimals that will be received/credited to the recipient on the remote OFT instance.
(uint256 amountSentLD, uint256 amountReceivedLD) = _debit(
msg.sender,
_sendParam.amountLD,
_sendParam.minAmountLD,
_sendParam.dstEid
);
// @dev Builds the options and OFT message to quote in the endpoint.
(bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
// @dev Sends the message to the LayerZero endpoint and returns the LayerZero msg receipt.
msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
// @dev Formulate the OFT receipt.
oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);
}
function quote(
uint32 _dstEid,
address _to,
uint256 _amount,
bytes memory _options
) external view returns (MessagingFee memory fee) {
return _quote(_dstEid, abi.encodePacked(_to, _amount), _options, false);
}
function quote(
uint32 _dstEid,
bytes memory _message,
bytes memory _options
) external view returns (MessagingFee memory fee) {
return _quote(_dstEid, _message, _options, false);
}

According to layerzero Make sure that the arguments passed into the quote() function identically match the parameters used in the lzSend() function. If parameters mismatch, you may run into errors as your msg.value will not match the actual gas quote.

https://docs.layerzero.network/v2/developers/evm/oapp/overview#implementing-_lzreceive

Impact

The mismatch between lzsend and quote functions arguments mean gas will be erroneous which means more gas will be sent or less gas will be sent. In the case of less gas, it means the asset on the destination chain will be stuck.

One of to scenarios will happen: we waste excess gas, which is refunded to the lzReceive() caller (Layer Zero) OR we underprice the delivery cost, causing lzReceive() to revert and the asset stuck in limbo forever.

Tools Used

Manual Review

Recommendations

Make sure that the arguments passed into the quote() function identically match the parameters used in the lzSend() function. If parameters mismatch, you may run into errors as your msg.value will not match the actual gas quote.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect payload bytes in `quote()` they use `abi.encodePacked(_to, _amount)` instead of `abi.encodePacked(_to.addressToBytes32(), _amount)`

Appeal created

kwakudr Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Incorrect payload bytes in `quote()` they use `abi.encodePacked(_to, _amount)` instead of `abi.encodePacked(_to.addressToBytes32(), _amount)`

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.