TempleGold

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

Insufficient validation of `msg.value` used for cross-chain fees in `TempleTeleporter::teleport`

Summary

TempleTeleporter::teleport does not properly validate the msg.value sent with the transaction, potentially leading to issues with cross-chain transfers and loss of funds.

Vulnerability Details

In TempleTeleporter::teleport, the msg.value is directly passed to the _lzSend function without any validation:

function teleport(uint32 dstEid, address to, uint256 amount, bytes calldata options)
external
payable
override
returns (MessagingReceipt memory receipt)
{
if (amount == 0) revert CommonEventsAndErrors.ExpectedNonZero();
if (to == address(0)) revert CommonEventsAndErrors.InvalidAddress();
// Encodes the message before invoking _lzSend.
bytes memory _payload = abi.encodePacked(to.addressToBytes32(), amount);
// debit
temple.burnFrom(msg.sender, amount);
emit TempleTeleported(dstEid, msg.sender, to, amount);
@> receipt = _lzSend(dstEid, _payload, options, MessagingFee(msg.value, 0), payable(msg.sender));
}

The function uses msg.value as the native fee for the Layer Zero transfer without checking if it's sufficient to cover the required fees.

Impact

The impact of this vulnerability is twofold:

  • Users may lose their TEMPLE tokens if they don't provide enough ETH to cover the Layer Zero fees, as the tokens are burned before the cross-chain transfer is attempted.

  • Users may lose excess ETH if they provide more than necessary for the fees, as there's no mechanism to refund the excess amount.

Tools Used

Manual code review

Recommendations

Implement a fee estimation mechanism using the existing quote function:

function teleport(uint32 dstEid, address to, uint256 amount, bytes calldata options)
external
payable
override
returns (MessagingReceipt memory receipt)
{
if (amount == 0) revert CommonEventsAndErrors.ExpectedNonZero();
if (to == address(0)) revert CommonEventsAndErrors.InvalidAddress();
bytes memory _payload = abi.encodePacked(to.addressToBytes32(), amount);
+ MessagingFee memory fee = _quote(dstEid, _payload, options, false);
+ if (msg.value < fee.nativeFee) revert InsufficientFee(fee.nativeFee, msg.value);
// Burn tokens
temple.burnFrom(msg.sender, amount);
emit TempleTeleported(dstEid, msg.sender, to, amount);
- receipt = _lzSend(dstEid, _payload, options, MessagingFee(msg.value, 0), payable(msg.sender));
+ receipt = _lzSend(dstEid, _payload, options, MessagingFee(fee.nativeFee, 0), payable(msg.sender));
+ // Refund any excess ETH
+ if (msg.value > fee.nativeFee) {
+ payable(msg.sender).transfer(msg.value - fee.nativeFee);
+ }
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Fee validation issue in send

Support

FAQs

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