Submitted on Apr 30th 2024 at 22:36:45 UTC by @marchev for Boost | Alchemix
Report ID: #30565
Report type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol
Impacts:
- Contract fails to deliver promised returns, but doesn't lose value
veALCX is intended to be ERC721 compliant. However, it does not comply with ERC721 due to broken EIP165 implementation which is mandated by the ERC721 specification.
The ERC721 specification states the following:
Every ERC-721 compliant contract must implement the
ERC721
andERC165
interfaces
This means that every compliant ERC721 token must implement EIP-165 and return true
for all supported interfaces. veALCX (VotingEscrow.sol
) implements both IERC721
and IERC721Metadata
. However, the VotingEscrow#supportInterface()
does not work as intended:
function supportsInterface(bytes4 _interfaceID) external pure returns (bool) {
revert("function not supported");
}
As per the EIP-165 specification, this implementation does not comply with EIP-165 (which is mandated by ERC721):
How to Detect if a Contract Implements ERC-165
- The source contract makes a
STATICCALL
to the destination address with input data:0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000
and gas 30,000. This corresponds tocontract.supportsInterface(0x01ffc9a7)
.- If the call fails or return false, the destination contract does not implement ERC-165.
Thus, VotingEscrow
does not implement EIP-165 and is not ERC721 compliant.
In pursuit of thoroughness and transparency, it's crucial to reference Finding 6.45 in Chainsecurity's audit which reports broken/partial EIP165 support. However, the applied fix is incorrect and breaks the intended compliance with ERC721. Recognizing and addressing the currently reported issue is vital for the compliance and composability of the veALCX token.
The token does not comply with the ERC721 standard, which causes composability and interoperability issues. This leads to failures when other contracts and DApps expect standard behaviors that the token does not provide, potentially causing disruptions, reducing its utility, and diminishing trust in the token's reliability.
Problematic implementation:
Docs references which state that ERC721 compliance is expected:
-
https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol#L16
-
https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/CONTRACTS.md
Add the following test to src/test/VotingEscrow.t.sol
:
function test_eip165_compliance_is_broken() public {
// As per https://eips.ethereum.org/EIPS/eip-721#specification:
// "Every ERC-721 compliant contract must implement the ERC721 and ERC165 interfaces"
assertEq(veALCX.supportsInterface(0x01ffc9a7), true); // ERC165
assertEq(veALCX.supportsInterface(0x80ac58cd), true); // ERC721
assertEq(veALCX.supportsInterface(0x5b5e139f), true); // ERC721Metadata
}
Make sure the following entries are updated in Makefile
:
# file to test
FILE=VotingEscrow
# specific test to run
TEST=test_eip165_compliance_is_broken
Run the PoC via make test_file_test