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))
);
}