TempleGold

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

_lzReceive() would always revert due to using abi.decode to decode data which were encoded using abi.encodePacked

Summary

Message received cross-chain would revert due to improper encoding/decoding.

Vulnerability Details

Users can teleport there tokens by burning on one chain then minting on the other chain using layerzero,
The issue is the encoded payload uses abi.encodePacked to encode it while on the recieving it uses abi.decode() to decode the payload, This is wrong as abi.encodePacked cannot be decoded using abi.decode().

https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleTeleporter.sol#L52

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);//@audit-issue
// 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));
}
function _lzReceive(
Origin calldata /*_origin*/,
bytes32 /*_guid*/,
bytes calldata _payload,
address /*_executor,*/, // Executor address as specified by the OApp.
bytes calldata /*_extraData */ // Any extra data or options to trigger on receipt.
) internal override {
// Decode the payload to get the message
(address _recipient, uint256 _amount) = abi.decode(_payload, (address, uint256));//@audit-issue
temple.mint(_recipient, _amount);
}

https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleTeleporter.sol#L107

This would result in a revert and brick the layerzero integration and users would not be able to recieving their burnt token.

Proof of Concept: A simple test with chisel:

address to = address(1);
uint256 amount = uint256(350);
bytes memory _payload = abi.encodePacked(to, amount);
➜ (address addr, uint256 amountdecoded) = abi.decode(_payload, (address, uint256));//@audit-info reverts
Traces:
[804] 0xBd770416a3345F91E4B34576cb804a576fa48EB1::run()
└─ ← [Revert] EvmError: Revert
➜ _payload = abi.encode(to, amount);//@info encoding using abi.encode()
➜ (address addr, uint256 amountdecoded) = abi.decode(_payload, (address, uint256));
➜ addr
Type: address
└ Data: 0x0000000000000000000000000000000000000001

Impact

Token burnt through teleport() would not be minted on the recieving chain resulting in loss of funds to the user.
Complete DoS of layerzero integration.

Tools Used

Manual Review

Recommendations

Use abi.encode() in encoding payload or use assembly in parsing the payload on the recieving end.

Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

`abi.encodePacked` to encode it while on the recieving it uses `abi.decode()` to decode the payload and it doesn't work like that

Support

FAQs

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