NFTBridge
60,000 USDC
View results
Submission Details
Severity: medium
Invalid

Inconsistent Handling of Contract Calls in TokenUtil::_callBaseUri Causing Unexpected Reverts

Summary

A security vulnerability was identified in the testFuzzCallBaseUri function while testing the TokenUtil::_callBaseUri logic. The function attempts to retrieve a base URI from an ERC721 or ERC1155 contract by trying two different function signatures (_baseUri() and baseUri()). However, when called on addresses that do not implement these signatures, the function causes unexpected reverts.

Vulnerability Details

The TokenUtil::_callBaseUri function tries to execute static calls to check for _baseUri() and baseUri() functions in the provided contract address. If these function signatures do not exist, it results in a revert, which was observed during fuzz testing.

  • Code Snippet (_callBaseUri):

function _callBaseUri(address collection) internal view returns (bool, string memory) {
bool success;
uint256 returnSize;
uint256 returnValue;
bytes memory ret;
bytes[2] memory encodedSignatures =
[abi.encodeWithSignature("_baseUri()"), abi.encodeWithSignature("baseUri()")];
for (uint256 i = 0; i < 2; i++) {
bytes memory encodedParams = encodedSignatures[i];
assembly {
success := staticcall(gas(), collection, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
if success {
returnSize := returndatasize()
returnValue := mload(0x00)
ret := mload(0x40)
mstore(ret, returnSize)
returndatacopy(add(ret, 0x20), 0, returnSize)
// update free memory pointer
mstore(0x40, add(add(ret, 0x20), add(returnSize, 0x20)))
}
}
if (success && returnSize >= 0x20 && returnValue > 0) {
return (true, abi.decode(ret, (string)));
}
}
return (false, "");
}

POC

The fuzz test for the testFuzzCallBaseUri function resulted in a failure when called on the address `0x0000000000000000000000000000000000000002. This indicates a revert during execution due to non-existent function signatures.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../src/token/TokenUtil.sol";
import "forge-std/Test.sol";
import "openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
import "openzeppelin-contracts/contracts/token/ERC1155/ERC1155.sol";
contract TokenUtilFuzzTest is Test {
// Dummy ERC721 and ERC1155 tokens for testing
DummyERC721 private erc721;
DummyERC1155 private erc1155;
function setUp() public {
erc721 = new DummyERC721("Dummy ERC721", "DERC721");
erc1155 = new DummyERC1155("");
}
function testFuzzCallBaseUri(address collection) public {
// Ensure the address is a contract
uint256 size;
assembly {
size := extcodesize(collection)
}
if (size == 0) {
vm.expectRevert();
TokenUtil._callBaseUri(collection);
return;
}
bool success;
string memory result;
(success, result) = TokenUtil._callBaseUri(collection);
if (success) {
emit log_string(result); // Log the result if successful
}
}
}
// Ensure the contract implements the required ERC721 interface
contract DummyERC721 is ERC721 {
constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
function _baseURI() internal view virtual override returns (string memory) {
return "https://dummybaseuri.com/";
}
function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);
}
// Ensure token ID is valid and minted before use
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "ERC721: invalid token ID");
return super.tokenURI(tokenId);
}
}
contract DummyERC1155 is ERC1155 {
constructor(string memory initialUri) ERC1155(initialUri) {}
function mint(address to, uint256 id, uint256 amount, bytes memory data) public {
_mint(to, id, amount, data);
}
function uri(uint256 tokenId) public view virtual override returns (string memory) {
return string(abi.encodePacked("https://dummyuri.com/token/", Strings.toString(tokenId)));
}
}

Impact

Security Impact: Medium

The primary risk is that the TokenUtil::_callBaseUri function may cause unexpected reverts for contracts that do not implement the expected function signatures. This has the potential to disrupt the functioning of dApps relying on this utility, leading to degraded user experience or unexpected failures in contract interactions.

Tools Used

  • Manuel review

  • Foundry

Recommendations

To reduce the risk of unexpected reverts, it is recommended to update the _callBaseUri function to include better error handling.

Updates

Lead Judging Commences

n0kto Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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