DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: medium
Valid

Improper Domain Separator Hash in _domainSeparatorV4() Function

Summary

The _domainSeparatorV4() function in the LibTractor library uses an incorrect type hash which does not match the format of data it is supposed to represent. In EIP-712, the domain separator should match the format: EIP712Domain(string name, string version, uint256 chainId, address verifyingContract). However, the function is currently using BLUEPRINT_TYPE_HASH intended for a different data structure: Blueprint(address publisher, bytes data, bytes operatorData, uint256 maxNonce, uint256 startTime, uint256 endTime). This mismatch leads to incorrect domain separation, causing blueprint-based signature verification to fail.

Vulnerability Details

The EIP-712 standard specifies a domain separator format using the type hash for the following data structure:

EIP712 Domain (string name, string version, uint256 chainId, address verifyingContract)

However, in the current implementation:

function _domainSeparatorV4() internal view returns (bytes32) {
return
keccak256(
abi.encode(
@> BLUEPRINT_TYPE_HASH,
TRACTOR_HASHED_NAME,
TRACTOR_HASHED_VERSION,
C.getChainId(),
address(this)
)
);
}

The function incorrectly uses BLUEPRINT_TYPE_HASH instead of EIP712_TYPE_HASH. BLUEPRINT_TYPE_HASH is meant for:

Blueprint(address publisher, bytes data, bytes operatorData, uint256 maxNonce, uint256 startTime, uint256 endTime);

This mismatch results in an incorrect domain separator.

Impact

  1. Signature Verification Failure: Because the type hash used in the domain separator does not match the required format, any off-chain signatures generated expect the domain to be compliant with EIP712Domain will not match the calculated on-chain domain separator. As a result, all such signature verifications will fail.

POC

To demonstrate and prove the issue with the incorrect domain separator, we'll use Foundry for testing. The objective is to show that using the incorrect type hash results in domain separators that do not match the expected hash needed for EIP-712 compliant signature verification. We will compare the incorrect domain separator with the corrected one and validate the findings.

Foundry Test

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.9.0;
import "forge-std/Test.sol";
import "../../../contracts/libraries/LibTractor.sol";
// Mock contract to mimic the necessary external dependencies
contract MockC {
function getChainId() public view returns (uint256) {
return block.chainid;
}
}
contract TestDomainSeparator is Test {
MockC mockC;
address verifyingContract;
// Define the constants manually since we can't access them directly
bytes32 private constant EIP712_TYPE_HASH = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
bytes32 private constant TRACTOR_HASHED_NAME = keccak256(bytes("Tractor"));
bytes32 private constant TRACTOR_HASHED_VERSION = keccak256(bytes("1"));
bytes32 private constant BLUEPRINT_TYPE_HASH = keccak256(
"Blueprint(address publisher,bytes data,bytes operatorData,uint256 maxNonce,uint256 startTime,uint256 endTime)"
);
function setUp() public {
mockC = new MockC();
verifyingContract = address(this);
}
// Correct domain separator using EIP712_TYPE_HASH
function correctDomainSeparator() internal view returns (bytes32) {
return keccak256(
abi.encode(
EIP712_TYPE_HASH,
TRACTOR_HASHED_NAME,
TRACTOR_HASHED_VERSION,
mockC.getChainId(),
verifyingContract
)
);
}
function testIncorrectDomainSeparator() public {
// Calculate the supposed domain separator using the incorrect BLUEPRINT_TYPE_HASH
bytes32 incorrectSeparator = keccak256(
abi.encode(
BLUEPRINT_TYPE_HASH,
TRACTOR_HASHED_NAME,
TRACTOR_HASHED_VERSION,
mockC.getChainId(),
verifyingContract
)
);
// Ensure the wrong type hash does not produce the expected domain separator
bytes32 expectedCorrectSeparator = correctDomainSeparator();
assertFalse(incorrectSeparator == expectedCorrectSeparator, "Incorrect type hash should not match expected correct domain separator");
// Calculate the correct domain separator using EIP712_TYPE_HASH
bytes32 calculatedCorrectSeparator = keccak256(
abi.encode(
EIP712_TYPE_HASH,
TRACTOR_HASHED_NAME,
TRACTOR_HASHED_VERSION,
mockC.getChainId(),
verifyingContract
)
);
// Ensure the correct domain separator matches the expected one
assertEq(calculatedCorrectSeparator, expectedCorrectSeparator, "Correct domain separator did not match expected value");
}
}

Explanation

  1. SetUp: We create a mock contract MockC to mimic getting the chain ID and set up the test environment by fetching the contract address.

  2. Correct Domain Separator: A helper function correctDomainSeparator is defined to calculate the correct domain separator using EIP712_TYPE_HASH.

  3. Test Function:

    • testIncorrectDomainSeparator calculates the supposed domain separator using the incorrect BLUEPRINT_TYPE_HASH and verifies that it does not match the correct domain separator.

    • The function then calculates the correct domain separator using EIP712_TYPE_HASH and verifies that it matches the expected correct separator.

This Foundry test clearly demonstrates the issue and the impact of using the incorrect type hash in _domainSeparatorV4(), validating the need for the recommended correction.

Tools Used

  • Manual Code Review

  • Foundry for testing and validation.

Recommendations

To resolve this issue, update the _domainSeparatorV4() function to use EIP712_TYPE_HASH when encoding the domain separator:

function _domainSeparatorV4() internal view returns (bytes32) {
return
keccak256(
abi.encode(
- BLUEPRINT_TYPE_HASH,
+ EIP712_TYPE_HASH,
TRACTOR_HASHED_NAME,
TRACTOR_HASHED_VERSION,
C.getChainId(),
address(this)
)
);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Tractor not compliant to EIP712 requirement because it's using the type hash of the blueprint, not the EIP712Domain

Appeal created

deadrosesxyz Auditor
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Tractor not compliant to EIP712 requirement because it's using the type hash of the blueprint, not the EIP712Domain

Support

FAQs

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