Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

NativeMetaTransaction.hashMetaTransaction() will not work because of abi.encodePacked

Summary

When sending data to a low level call, NativeMetaTransaction.hashMetaTransaction() uses abi.encodePacked instead of abi.encodeWithSelector. The data packed will become condensed which will not have the padding needed for a proper low level call.

Vulnerability Details

In NativeMetaTransaction.sol, there is a function that is supposed to be called by the relayer for the user. This function uses abi.encodePacked as part of the data called instead of abi.encodeWithSelector().

function executeMetaTransaction(
// Append userAddress and relayer address at the end to extract it from calling context
(bool success, bytes memory returnData) = address(this).call{value: msg.value}(
abi.encodePacked(functionSignature, userAddress)
);
require(success, "Function call not successful");

Since address is used, the bytes are packed, which makes data have lesser bytes than intended to complete a successful call.

Take a look at this Remix test:

pragma solidity 0.8.20;
contract Test {
address public name;
bytes4 public functionSignature = bytes4(keccak256("take(address)"));
function take(address _address) public {
name = _address;
}
function testPacked() public returns (bytes memory) {
(bool success, bytes memory returnData) = address(this).call(
abi.encodePacked(bytes4(keccak256("take(address)")),address(this))
);
require(success, "Function call not successful");
}
function testSelector() public returns (bytes memory) {
(bool success, bytes memory returnData) = address(this).call(
abi.encodeWithSelector(bytes4(keccak256("take(address)")),address(this))
);
require(success, "Function call not successful");
}
fallback() payable external {}
function test1() public view returns (bytes memory) {
return abi.encodePacked(bytes4(keccak256("take(address)")),address(this));
}
function test2() public view returns (bytes memory) {
return abi.encodeWithSelector(bytes4(keccak256("take(address)")),address(this));
}
}

Calling testSelector() succeeds but calling testPacked() fails. abi.encodePacked compacts the bytes which makes it unreadable through a low level call.

abi.encodePacked() returns 0x4d44e6635c7078010ea1046720d08daef080e1f75bb13682 whereas abi.encodeWithSelector() returns 0x4d44e6630000000000000000000000005c7078010ea1046720d08daef080e1f75bb13682

Impact

Function cannot work.

Tools Used

Manual Review

Recommendations

Change abi.encodePacked to abi.encodeWithSelector.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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