## Summary
A mismatch between the `quote()` and `teleport()` payload encoding in the `TempleTeleporter` contract can lead to incorrect fee estimations, causing the `teleport()` transaction to fail due to insufficient fees. This is caused by the different handling of the `address _to` parameter in the two functions, leading to two different payloads where the `quote()` payload's size is smaller than `teleport()`'s.
## Vulnerability Details
The root cause of the vulnerability is the difference in payload encoding between the `quote()` and `teleport()` functions. Specifically, the `teleport()` function utilizes an `addressToBytes32()` function to cast the `_to` parameter to `bytes32` and adds extra padding before encoding.
https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleTeleporter.sol#L52
```solidity
// File: protocol/contracts/templegold/TempleTeleporter.sol
43: function teleport(
...
51: // Encodes the message before invoking _lzSend.
52: bytes memory _payload = abi.encodePacked(to.addressToBytes32(), amount);// <= FOUND
...
58: }
```
Conversely, the `quote()` function directly employs `encodePacked(_to, _amount)` without initially casting `_to` to `bytes32`. Since the `address` type is 20-byte long, this variation in encoding methodology results in a payload of 12 bytes smaller.
https://github.com/Cyfrin/2024-07-templegold/blob/main/protocol/contracts/templegold/TempleTeleporter.sol#L93
```solidity
// File: protocol/contracts/templegold/TempleTeleporter.sol
87: function quote(
...
91: bytes memory _options
92: ) external view returns (MessagingFee memory fee) {
93: return _quote(_dstEid, abi.encodePacked(_to, _amount), _options, false); // <= FOUND: abi.encodePacked(_to, _amount) generates a payload 12 byte smaller than abi.encodePacked(_to.addressToBytes32(), _amount)
94: }
```
Moreover, by referencing LayerZero's quoting process at https://arbiscan.io/address/0x975bcD720be66659e3EB3C0e4F1866a3020E493A#code#F25#L164, we can see that the message size also plays a factor in fee calculation of the executor quote:
```solidity
/// @dev the abstract process for quote() is:
/// 0/ split out the executor options and options of other workers
/// 1/ quote workers
/// 2/ quote executor
/// 3/ quote treasury
/// @return nativeFee, lzTokenFee
function _quote(
address _sender,
uint32 _dstEid,
uint256 _msgSize,
bool _payInLzToken,
bytes calldata _options
) internal view returns (uint256, uint256) {
...
// @audit executor quote depends on _msgSize
@> nativeFee += ILayerZeroExecutor(config.executor).getFee(_dstEid, _sender, _msgSize, executorOptions);
...
}
```
Did a test with `chisel`, we can get the payload disparity as follows.
> quotePayload.length = 0x34 or 52 in decimal
> teleportPayload.length = 0x40 or 64 in decimal
That 12 unit in length difference means that if a user relying on `quote()` call would make a `teleport()` transaction with a `msg.value` less than the required amount, potentially leading to transaction failures due to insufficient funds.
```sh
➜ bytes memory quotePayload = abi.encodePacked(to, uint256(1));
➜ bytes memory teleportPayload = abi.encodePacked(bytes32(uint256(uint160(to))), uint256(1)); // equivalent to addressToBytes32(to)
➜ quotePayload
Type: dynamic bytes
├ Hex (Memory):
├─ Length ([0x00:0x20]): 0x0000000000000000000000000000000000000000000000000000000000000034
├─ Contents ([0x20:..]): 0xe3d1a117df7dcac2eb0ac8219341bad92f18dac10000000000000000000000000000000000000000000000000000000000000001000000000000000000000000
├ Hex (Tuple Encoded):
├─ Pointer ([0x00:0x20]): 0x0000000000000000000000000000000000000000000000000000000000000020
├─ Length ([0x20:0x40]): 0x0000000000000000000000000000000000000000000000000000000000000034
└─ Contents ([0x40:..]): 0xe3d1a117df7dcac2eb0ac8219341bad92f18dac10000000000000000000000000000000000000000000000000000000000000001000000000000000000000000
➜ teleportPayload
Type: dynamic bytes
├ Hex (Memory):
├─ Length ([0x00:0x20]): 0x0000000000000000000000000000000000000000000000000000000000000040
├─ Contents ([0x20:..]): 0x000000000000000000000000e3d1a117df7dcac2eb0ac8219341bad92f18dac10000000000000000000000000000000000000000000000000000000000000001
├ Hex (Tuple Encoded):
├─ Pointer ([0x00:0x20]): 0x0000000000000000000000000000000000000000000000000000000000000020
├─ Length ([0x20:0x40]): 0x0000000000000000000000000000000000000000000000000000000000000040
└─ Contents ([0x40:..]): 0x000000000000000000000000e3d1a117df7dcac2eb0ac8219341bad92f18dac10000000000000000000000000000000000000000000000000000000000000001
```
## Impact
The severity of this vulnerability is significant, as it could lead to transaction failures and financial losses in terms of wasted Gas for users. The incorrect quote estimate, stemming from the mismatch payload encoding, could result in transactions failing due to insufficient fees, disrupting the seamless operation of cross-chain transfers.
## Tools Used
Manual Review
## Recommendations
Modify the `quote()` function to ensure consistency with the `teleport()` function by returning the encoded payload with the `address _to` parameter cast to `bytes32`. The updated function should be:
```patch
- return _quote(_dstEid, abi.encodePacked(_to, _amount), _options, false);
+ return _quote(_dstEid, abi.encodePacked(_to.addressToBytes32(), _amount), _options, false);
```