Relevant GitHub Links
Refrences
Summary
The SablierFlowBase
contract does not adhere to the EIP4906
standard, as it fails to implement the required supportsInterface(bytes4)
function to confirm compatibility with the IERC4906
interface. This omission can cause integration issues for contracts that rely on EIP-165
to verify interface support.
Vulnerability Details:
The ISablierFlowBase
interface inherits from IERC4906
, but the SablierFlowBase
contract does not override the supportsInterface()
function.
interface ISablierFlowBase is
IERC4906,
IERC721Metadata,
IAdminable
Impact Details
The lack of a proper supportsInterface
implementation can cause significant compatibility issues. Systems that check for EIP-165
compliance may fail to interact correctly with the SablierFlowBase
contract. This could lead to failures in contract interactions, integrations, and potentially disrupt decentralized applications relying on SablierFlowBase
.
POC:
Add the following test file to the test folder:
tests\Chista0xAudit.t.sol
pragma solidity >=0.8.22;
import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import { Base_Test } from "./Base.t.sol";
import { console } from "forge-std/src/console.sol";
contract Chista0xAudit is Base_Test {
function test_supportsInterface_IERC165() external view {
bool res = flow.supportsInterface(type(IERC165).interfaceId);
assertEq(res, true, "EIP165 interface not supported");
}
function test_supportsInterface_IERC721() external view {
bool res = flow.supportsInterface(type(IERC721).interfaceId);
assertEq(res, true, "IERC721 interface not supported");
}
function test_supportsInterface_IERC721Metadata() external view {
bool res = flow.supportsInterface(type(IERC721Metadata).interfaceId);
assertEq(res, true, "IERC721Metadata interface not supported");
}
function test_supportsInterface_IERC4906() external view {
bool res = flow.supportsInterface(type(IERC4906).interfaceId);
assertEq(res, true, "IERC4906 interface not supported");
}
}
Run the test with the command forge test --mc Chista0xAudit
Test output:
Ran 4 tests for tests/Chista0xAudit.t.sol:Chista0xAudit
[PASS] test_supportsInterface_IERC165() (gas: 9961)
[FAIL. Reason: IERC4906 interface not supported: false != true] test_supportsInterface_IERC4906() (gas: 9931)
[PASS] test_supportsInterface_IERC721() (gas: 9882)
[PASS] test_supportsInterface_IERC721Metadata() (gas: 9997)
Suite result: FAILED. 3 passed; 1 failed; 0 skipped; finished in 27.76ms (1.42ms CPU time)
Ran 1 test suite in 30.65ms (27.76ms CPU time): 3 tests passed, 1 failed, 0 skipped (4 total tests)
Failing tests:
Encountered 1 failing test in tests/Chista0xAudit.t.sol:Chista0xAudit
[FAIL. Reason: IERC4906 interface not supported: false != true] test_supportsInterface_IERC4906() (gas: 9931)
Recommendation:
add supportsInterface
function to the SablierFlowBase
contract.
src\abstracts\SablierFlowBase.sol:
...
+ import { IERC4906 } from "@openzeppelin/contracts/interfaces/IERC4906.sol";
+ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
...
abstract contract SablierFlowBase is
Adminable, // 1 inherited component
ISablierFlowBase, // 5 inherited component
ERC721 // 6 inherited components
{
...
+ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
+ return interfaceId == type(IERC4906).interfaceId || super.supportsInterface(interfaceId);
+ }
...
}
Tools Used
Manual code review / Foundry tests