TempleGold

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

Users using account abstraction wallets or multisig wallets won't be credited on the destination chain.

Summary

Users using account abstraction wallets or multisig wallets won't be credited on the destination chain.

Vulnerability Details

Users with account abstraction wallets have different addresses across different chains for the same account. Also, multisigs are contracts deployed on chains and that's why destination chain address, which corresponds to source chain address won't be owned by the same person.

In the send() function of TempleGold 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(); }
/// 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);
}

User can only cross-chain transfer to self address.

if (msg.sender != _to) { revert ITempleGold.NonTransferrable(msg.sender, _to); }

Now, when _lzReceive() is called on the destination chain, the same self address is credited:

function _lzReceive(
Origin calldata _origin,
bytes32 _guid,
bytes calldata _message,
address /*_executor*/, // @dev unused in the default implementation.
bytes calldata /*_extraData*/ // @dev unused in the default implementation.
) internal virtual override {
// @dev The src sending chain doesnt know the address length on this chain (potentially non-evm)
// Thus everything is bytes32() encoded in flight.
address toAddress = _message.sendTo().bytes32ToAddress();
// @dev Credit the amountLD to the recipient and return the ACTUAL amount the recipient received in local decimals
uint256 amountReceivedLD = _credit(toAddress, _toLD(_message.amountSD()), _origin.srcEid);
/// @dev Disallow further execution on destination by ignoring composed message
if (_message.isComposed()) { revert CannotCompose(); }
emit OFTReceived(_guid, _origin.srcEid, toAddress, amountReceivedLD);
}

Impact

The address may not be same on the destination chain and thus incorrect address will be credited. This is loss of funds for the message sender.

Tools Used

Manual Analysis

Relevant Github Links

  1. send(): https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/TempleGold.sol#L290

  2. _lzReceive(): https://github.com/Cyfrin/2024-07-templegold/blob/57a3e597e9199f9e9e0c26aab2123332eb19cc28/protocol/contracts/templegold/TempleGold.sol#L333

Recommendations

Give the user the option to pass in the address the funds should be credited to on the l2 by removing this check in the send() function:

if (msg.sender != _to) { revert ITempleGold.NonTransferrable(msg.sender, _to); }
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Account abstraction, Multisig, Any other contract based solution that doesn't share the same address across chains will lose it's TGLD in teleport.

Support

FAQs

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