Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Invalid

Non EIP-712 compliant operation hashing in `TimelockController` enables transaction malleability

Summary

The TimelockController::hashOperationBatch() function directly hashes arrays using keccak256 without proper EIP-712 encoding, violating the specification and enabling transaction malleability.

Vulnerability Details

The hashOperationBatch function uses keccak256(abi.encode()) directly on arrays:

function hashOperationBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas,
bytes32 predecessor,
bytes32 salt
) public pure returns (bytes32) {
@> return keccak256(abi.encode(targets, values, calldatas, predecessor, salt));
}

This violates EIP-712 which requires arrays to be encoded by hashing each element individually and then hashing the array of hashes. The current implementation allows different array representations to produce the same hash, enabling transaction malleability.

Impact

  • Transaction malleability: Different array representations can produce identical operation hashes

  • Potential front-running on scheduled operations

  • Non-compliance with EIP-712 standard reduces cross-platform compatibility

Tools Used

Manual review

Recommendations

Implement EIP-712 compliant array hashing:

function hashOperationBatch(
address[] calldata targets,
uint256[] calldata values,
bytes[] calldata calldatas,
bytes32 predecessor,
bytes32 salt
) public pure returns (bytes32) {
bytes32[] memory targetHashes = new bytes32[](targets.length);
bytes32[] memory valueHashes = new bytes32[](values.length);
bytes32[] memory calldataHashes = new bytes32[](calldatas.length);
for(uint i = 0; i < targets.length; i++) {
targetHashes[i] = keccak256(abi.encode(targets[i]));
valueHashes[i] = keccak256(abi.encode(values[i]));
calldataHashes[i] = keccak256(abi.encode(calldatas[i]));
}
return keccak256(abi.encode(
keccak256(abi.encode(targetHashes)),
keccak256(abi.encode(valueHashes)),
keccak256(abi.encode(calldataHashes)),
predecessor,
salt
));
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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