Summary
The _domainSeparatorV4 calculation is incorrect in LibTractor.sol which causes DoS of TractorFacet.sol functionality.
Vulnerability Details
_domainSeparatorV4() is implemented as:
function _domainSeparatorV4() internal view returns (bytes32) {
return keccak256(
abi.encode(BLUEPRINT_TYPE_HASH, TRACTOR_HASHED_NAME, TRACTOR_HASHED_VERSION, C.getChainId(), address(this))
);
}
Here, BLUEPRINT_TYPE_HASH is defined as:
bytes32 public constant BLUEPRINT_TYPE_HASH = keccak256(
"Blueprint(address publisher,bytes data,bytes operatorData,uint256 maxNonce,uint256 startTime,uint256 endTime)"
);
But, BLUEPRINT_TYPE_HASH should be used for calculating Blueprint hash not domain separator for EIP712 signatures. Thus, _hashTypedDataV4() will return incorrect EIP712 compliant hash.
function _hashTypedDataV4(bytes32 structHash) internal view returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash));
}
Impact
DoS of TractorFacet contract functionality as verifyRequisition modifier calls _getBlueprintHash() function of LibTractor.sol to get the blueprint which will be calculated incorrectly because of incorrect domain seperator calculation.
modifier verifyRequisition(LibTractor.Requisition calldata requisition) {
bytes32 blueprintHash = LibTractor._getBlueprintHash(requisition.blueprint);
require(blueprintHash == requisition.blueprintHash, "TractorFacet: invalid hash");
address signer =
ECDSA.recover(MessageHashUtils.toEthSignedMessageHash(requisition.blueprintHash), requisition.signature);
require(signer == requisition.blueprint.publisher, "TractorFacet: signer mismatch");
_;
}
The hashes won't match and the modifier will revert. This will cause in reverting of other subsequent functions using the verifyRequisition modifier like tractor(), cancelBlueprint().
Tools Used
Manual Analysis
Relevant Links
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/4e0ad0b964f74a1b4880114f4dd5b339bc69cd3e/protocol/contracts/libraries/LibTractor.sol#L177
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/4e0ad0b964f74a1b4880114f4dd5b339bc69cd3e/protocol/contracts/beanstalk/farm/TractorFacet.sol#L33-L34
Recommendations
Modify the _domainSeparatorV4() function to use the EIP712_TYPE_HASH:
function _domainSeparatorV4() internal view returns (bytes32) {
return keccak256(
abi.encode(EIP712_TYPE_HASH, TRACTOR_HASHED_NAME, TRACTOR_HASHED_VERSION, C.getChainId(), address(this))
);
}