TempleGold

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

Potential Stuck Ether in `send` and `teleport` Functions

Summary

The TempleGold.sol and TempleTeleporter.sol contracts contain send() and teleport() functions, respectively, that are marked as payable. These functions allow users to send Ether to cover cross-chain transfer fees. However, both functions lack a mechanism to refund excess Ether, leading to potential funds being stuck in the contracts.

Vulnerability Details

Both the send function in the TempleGold.sol contract and the teleport function in the TempleTeleporter.sol contract are marked as payable, allowing them to receive Ether. However, neither function implements any mechanism to handle or refund excess Ether sent by users. This creates a vulnerability where surplus Ether can become permanently inaccessible, stuck in the contract.

In the send() function, users need to send Ether to cover the fees for cross-chain transfers using the LayerZero protocol. In the teleport() function, users send Ether to cover the costs associated with the cross-chain teleportation of Temple tokens. Users of the teleport function are expected to use the quote() function to estimate the required fee before executing the transaction. However, due to fluctuations in gas prices and potential inaccuracies in the estimation process, users may end up sending more Ether than needed.

When excess Ether is sent to these functions, it remains in the contract as there are no checks or mechanisms to refund the surplus. This not only leads to users losing their Ether but also results in unnecessary accumulation of Ether within the contract, which cannot be accessed or used.

The vulnerability lies in the lack of refund logic for handling excess Ether, which should be returned to the sender if the actual fee is lower than the amount sent. Without this, the contract effectively traps any extra Ether sent by users, leading to potential financial loss for users and inefficiency in the contract's Ether management.

Vulnerable code

Impact

The excess Ether sent to the contracts can accumulate over time, leading to significant funds being stuck and inaccessible. This issue can result in a loss of funds for users who accidentally send more Ether than required.

Tools Used

  • Manual Review

  • VS code

Recommendations

To prevent Ether from getting stuck in the contracts, implement a refund mechanism for any excess Ether sent to the send()and teleport() functions.

Updated send() function in TempleGold.sol contract:

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(); }
address _to = _sendParam.to.bytes32ToAddress();
if (msg.sender != _to) { revert ITempleGold.NonTransferrable(msg.sender, _to); }
uint256 requiredFee = // calculate required fee;
require(msg.value >= requiredFee, "Insufficient Ether sent");
uint256 excessFee = msg.value - requiredFee;
if (excessFee > 0) {
(bool refundSuccess, ) = msg.sender.call{value: excessFee}("");
require(refundSuccess, "Refund failed");
}
(uint256 amountSentLD, uint256 amountReceivedLD) = _debit(
msg.sender,
_sendParam.amountLD,
_sendParam.minAmountLD,
_sendParam.dstEid
);
(bytes memory message, bytes memory options) = _buildMsgAndOptions(_sendParam, amountReceivedLD);
msgReceipt = _lzSend(_sendParam.dstEid, message, options, _fee, _refundAddress);
oftReceipt = OFTReceipt(amountSentLD, amountReceivedLD);
emit OFTSent(msgReceipt.guid, _sendParam.dstEid, msg.sender, amountSentLD, amountReceivedLD);
}

Updated teleport() function in TempleTeleporter.sol contract:

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(); }
uint256 requiredFee = // calculate required fee;
require(msg.value >= requiredFee, "Insufficient Ether sent");
uint256 excessFee = msg.value - requiredFee;
if (excessFee > 0) {
(bool refundSuccess, ) = msg.sender.call{value: excessFee}("");
require(refundSuccess, "Refund failed");
}
bytes memory _payload = abi.encodePacked(to.addressToBytes32(), amount);
temple.burnFrom(msg.sender, amount);
emit TempleTeleported(dstEid, msg.sender, to, amount);
receipt = _lzSend(dstEid, _payload, options, MessagingFee(msg.value, 0), payable(msg.sender));
}

By implementing these changes, the contracts will ensure that any excess Ether sent by users is promptly refunded, preventing the accumulation of inaccessible funds.

Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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