Sparkn

CodeFox Inc.
DeFiFoundryProxy
15,000 USDC
View results
Submission Details
Severity: low
Valid

The `digest` calculation in `deployProxyAndDistributeBySignature` does not follow EIP-712 specification

Summary

The calculation of the digest done in ProxyFactory.deployProxyAndDistributeBySignature() does not follow the EIP-712 specification. It is missing the function's corresponding typeHash, as well as the hashStruct calculation of the data signature parameter, which are both defined in the EIP.

Not following the EIP specification will end up in unexpected integration failures with EIP712-compliant wallets or tooling that perform the encoding in the appropriate way.

Vulnerability Details

In ProxyFactory.deployProxyAndDistributeBySignature(), the digest is calculated as follows:

bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(contestId, data)
)
);

The EIP-712 specification defines the encoding of a message as:

"\x19\x01" ‖ domainSeparator ‖ hashStruct(message)

In the current implementation, "\x19\x01" and domainSeparator are correctly calculated and appended as per OpenZeppelin's _hashTypedDataV4() function, but hashStruct(message) is not respected.

The EIP defines that the hashStruct of a message is calculated from the hashing of the typeHash and the encoding of the data; and the former is currently missing in the digest calculation.

Additionally, the data parameter which is being included as part of the signature, is a bytes type, which the EIP defines as Dynamic. Dynamic types are encoded as the hash of the contents; and currently the data parameter is being encoded as-is.

Impact

The data being signed is not being encoded as per the EIP-712 specification, which will result in unexpected integration failures with EIP712-compliant wallets or tooling that perform the encoding in the appropriate way.

After looking at the tests, I would say this error was not caught since the tests themselves follow the same exact implementation for creating the data being signed. Usage of external libraries such as Ethers.js would have likely revealed this issue earlier.

Tools Used

Manual Review

Recommendations

Define and use the typeHash of the function.

  • Define the typeHash

bytes32 internal constant DEPLOY_AND_DISTRIBUTE_TYPEHASH = keccak256(
"DeployAndDistribute(bytes32 contestId,bytes data)"
);
  • Include it in the digest calculation

bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
DEPLOY_AND_DISTRIBUTE_TYPEHASH,
contestId,
...
)
)
);

Encode the dynamic data parameter as per the EIP-712 specification.

bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
DEPLOY_AND_DISTRIBUTE_TYPEHASH,
contestId,
keccak256(data)
)
)
);

Support

FAQs

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