Summary
The message length in TempleTeleporter.quote
is different from TempleTeleporter.teleport
.
Vulnerability Details
I will call the former quote1
and the latter quote2
.
function quote(uint32 _dstEid, bytes memory _message, bytes memory _options)
function quote(uint32 _dstEid, address _to, uint256 _amount, bytes memory _options)
quote2
uses abi.encodePacked
.
function quote(
uint32 _dstEid,
address _to,
uint256 _amount,
bytes memory _options
) external view returns (MessagingFee memory fee) {
return _quote(_dstEid, abi.encodePacked(_to, _amount), _options, false);
}
https://github.com/Cyfrin/2024-07-templegold/blob/6873abd52ddee3502fdefd95b83304687feb515b/protocol/contracts/templegold/TempleTeleporter.sol#L93
However, the test below uses abi.encode
for quote1
, which makes the length of the message 16 byte longer.
MessagingFee memory fee = aTT.quote(bEid, abi.encode(userB, tokensToSend), options);
MessagingFee memory feeRaw = aTT.quote(bEid, userB, tokensToSend, options);
assertEq(feeRaw.lzTokenFee, fee.lzTokenFee);
assertApproxEqAbs(feeRaw.nativeFee, fee.nativeFee, 20);
https://github.com/Cyfrin/2024-07-templegold/blob/6873abd52ddee3502fdefd95b83304687feb515b/protocol/test/forge/templegold/TempleTeleporter.t.sol#L66-L87
teleport
function makes the address to bytes32.
bytes memory _payload = abi.encodePacked(to.addressToBytes32(), amount);
https://github.com/Cyfrin/2024-07-templegold/blob/6873abd52ddee3502fdefd95b83304687feb515b/protocol/contracts/templegold/TempleTeleporter.sol#L52
OFTMsgCodec.addressToBytes32
zero-pads to the left, so abi.encode(userB, tokensToSend)
is the right way to
calculate the fee.
function addressToBytes32(address _addr) internal pure returns (bytes32) {
return bytes32(uint256(uint160(_addr)));
}
https://github.com/LayerZero-Labs/LayerZero-v2/blob/7aebbd7c79b2dc818f7bb054aed2405ca076b9d6/packages/layerzero-v2/evm/oapp/contracts/oft/libs/OFTMsgCodec.sol#L71-L73
$ chisel
-> address x = address(0x123);
-> bytes32(uint256(uint160(x)))
Type: bytes32
ā Data: 0x0000000000000000000000000000000000000000000000000000000000000123
Impact
Calculated fee is less by 16 than the necessary amount in TempleTeleporter.teleport
, so teleport
will fail if
a user sends its fee calculated from quote2
.
Tools Used
Manual review, foundry.
Recommendations
Fix as below.
- return _quote(_dstEid, abi.encodePacked(_to, _amount), _options, false);
+ return _quote(_dstEid, abi.encode(_to, _amount), _options, false);
https://github.com/Cyfrin/2024-07-templegold/blob/6873abd52ddee3502fdefd95b83304687feb515b/protocol/contracts/templegold/TempleTeleporter.sol#L93