Denial of Service (DoS) attacks pose a critical threat to decentralized applications (dApps). These attacks are not designed to steal funds, but rather to cripple a program’s functionality, making it unusable or inaccessible for legitimate users. This disruption can prevent crucial operations from executing, block user interactions, and severely erode trust in the application. Such incidents effectively “shut down” access, even if underlying assets remain secure. This section will detail common DoS attack methods found in smart contracts and, more importantly, provide robust strategies to defend against them, ensuring your dApps remain resilient and consistently available. 1. Avoid Unbounded Loops For collections that still need to be iterated (e.g., for data display in a dApp), implementing pagination is crucial to fetch items in smaller, manageable chunks, thus avoiding the block gas limit and potential DoS attacks. How Pagination Works Instead of trying to read an entire large array or list from your smart contract in one go (which can exceed the gas limit), pagination allows your frontend application to request data in smaller, defined segments. This distributes the gas cost over multiple, smaller transactions and prevents any single transaction from becoming too expensive. Examples of Pagination in Solidity Let’s illustrate with a simple example of a contract storing a list of user addresses. Vulnerable Example (Without Pagination): This function tries to return all addresses, which would fail if users array becomes too large. // VULNERABLE: Trying to return an entire unbounded arrayaddress[] public registeredUsers;function addRegisteredUser(address _user) public { registeredUsers.push(_user);}// This function will revert if registeredUsers.length is too largefunction getAllRegisteredUsers() public view returns (address[] memory) { return registeredUsers;} DoS Protected Example (With Pagination): Here, we provide functions that allow the frontend to request users in batches, controlling the gas cost. // DoS Protected: Paginationaddress[] public registeredUsers;function addRegisteredUser(address _user) public { registeredUsers.push(_user);}// Function to get the total count of registered usersfunction getTotalRegisteredUsersCount() public view returns (uint256) { return registeredUsers.length;}// Function to get a paginated list of users// _startIndex: the starting index for the slice// _count: the number of elements to retrieve from the startIndexfunction getPaginatedRegisteredUsers(uint256 _startIndex, uint256 _count) public view returns (address[] memory) { require(_startIndex <= registeredUsers.length, "Start index out of bounds"); uint256 endIndex = _startIndex + _count; if (endIndex > registeredUsers.length) { endIndex = registeredUsers.length; } uint256 actualCount = endIndex - _startIndex; address[] memory result = new address[](actualCount); for (uint256 i = 0; i < actualCount; i++) { result[i] = registeredUsers[_startIndex + i]; } return result;} How a Frontend Would Use It A frontend application (e.g., in React or plain JavaScript) would interact with this paginated contract like this: Get Total Count: First, call getTotalRegisteredUsersCount() to know how many users there are in total. Calculate Pages: Based on the total count, decide how many items to display per page (e.g., 10 or 20). Fetch Pages: Make repeated calls to getPaginatedRegisteredUsers(startIndex, count) as the user navigates through pages. For instance, to get the first 10 users, it would call getPaginatedRegisteredUsers(0, 10); for the next 10, it would call getPaginatedRegisteredUsers(10, 10), and so on. This way, no single transaction tries to fetch all data at once, keeping gas costs manageable and preventing DoS attacks due to excessive computation. 2. Guard Against Unexpected Reverts (External Call DoS) If your contract’s logic depends on the successful execution of an external call (e.g., sending Ether to an address), and that external call can be made to revert by a malicious actor, it can cause a DoS. Vulnerable Example (Auction Refund): Imagine an auction contract that automatically refunds the previous highest bidder when a new higher bid comes in. If the previous highest bidder is a malicious contract that always reverts when it receives Ether, the bid function would always fail, preventing anyone else from bidding. // VULNERABLE: DoS via external call revert address public highestBidder; uint256 public highestBid; function bid() public payable { require(msg.value > highestBid, "Bid must be higher"); if (highestBidder != address(0)) { // If highestBidder is a malicious contract that always reverts on Ether receipt, // this transfer will fail, causing the entire bid function to revert. payable(highestBidder).transfer(highestBid); // Or .send() or .call() } highestBidder = msg.sender; highestBid = msg.value; } Solution: Pull Payment Pattern (as shown above): By using a pull payment system, the contract doesn’t force a transfer to potentially malicious addresses. Users must explicitly call a withdraw function, isolating the failure to their own transaction if they are a malicious contract. 3. Consider Transaction Ordering Dependence (Front-running) While not a direct DoS in the sense of halting a contract, front-running can effectively deny a legitimate user their intended outcome by having a malicious transaction executed before theirs. This is often seen in decentralized exchanges or auction protocols. Scenario: An attacker sees your transaction to buy a rare NFT in the public mempool. They then submit a similar transaction with a higher gas price, ensuring their transaction is mined first, effectively “stealing” the NFT. Mitigation: Commit-Reveal Schemes: For sensitive operations like auctions or votes, users first commit a hashed version of their action, and only later reveal the actual action. This prevents others from knowing their intent beforehand. Time Delays: Implement delays so that sensitive actions can only be executed after a certain number of blocks, giving time for others to react if they see a front-running attempt. Using a Decentralized Sequencer/Relayer: In some Layer 2 solutions, transactions are ordered by a centralized or decentralized sequencer, which can help mitigate front-running risks. 4. Reentrancy Guards (Indirect DoS) While primarily a fund-draining vulnerability, a reentrancy attack can indirectly lead to a DoS if the recursive calls exhaust the gas limit or cause an unexpected state. Protecting against reentrancy is a fundamental security practice. Solution: Checks-Effects-Interactions Pattern: Always update the contract’s state before making any external calls. // Protected with Checks-Effects-Interactions function withdrawSafely() public { uint256 amount = balances[msg.sender]; // Check require(amount > 0, "No funds to withdraw"); balances[msg.sender] = 0; // Effect (update state BEFORE external call) // Interaction (external call) (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success, "Transfer failed"); } Solution: Reentrancy Guard: Use a mutex-like mechanism (e.g., OpenZeppelin’s ReentrancyGuard modifier) to prevent a function from being called again while it's still executing. // SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "@openzeppelin/contracts/security/ReentrancyGuard.sol";contract MyContract is ReentrancyGuard { // Example withdraw function protected against reentrancy attacks function withdraw() public nonReentrant { // withdrawal logic }} Conclusion: Engineering for Uninterrupted Decentralization Protecting your smart contracts from Denial of Service attacks is paramount to building truly reliable and user-friendly decentralized applications. While often overlooked in favor of direct financial security, a successful DoS attack can be just as crippling, effectively locking out users and halting critical operations. By diligently applying strategies such as avoiding unbounded loops, implementing pull payment patterns, considering transaction ordering, and utilizing reentrancy guards, you empower your smart contracts to withstand malicious attempts at disruption. Remember, a resilient smart contract not only secures assets but also guarantees continuous access and functionality, fostering user trust and contributing to a truly robust decentralized future. DoS Protection: Safeguarding Your Contract’s Availability was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this storyDenial of Service (DoS) attacks pose a critical threat to decentralized applications (dApps). These attacks are not designed to steal funds, but rather to cripple a program’s functionality, making it unusable or inaccessible for legitimate users. This disruption can prevent crucial operations from executing, block user interactions, and severely erode trust in the application. Such incidents effectively “shut down” access, even if underlying assets remain secure. This section will detail common DoS attack methods found in smart contracts and, more importantly, provide robust strategies to defend against them, ensuring your dApps remain resilient and consistently available. 1. Avoid Unbounded Loops For collections that still need to be iterated (e.g., for data display in a dApp), implementing pagination is crucial to fetch items in smaller, manageable chunks, thus avoiding the block gas limit and potential DoS attacks. How Pagination Works Instead of trying to read an entire large array or list from your smart contract in one go (which can exceed the gas limit), pagination allows your frontend application to request data in smaller, defined segments. This distributes the gas cost over multiple, smaller transactions and prevents any single transaction from becoming too expensive. Examples of Pagination in Solidity Let’s illustrate with a simple example of a contract storing a list of user addresses. Vulnerable Example (Without Pagination): This function tries to return all addresses, which would fail if users array becomes too large. // VULNERABLE: Trying to return an entire unbounded arrayaddress[] public registeredUsers;function addRegisteredUser(address _user) public { registeredUsers.push(_user);}// This function will revert if registeredUsers.length is too largefunction getAllRegisteredUsers() public view returns (address[] memory) { return registeredUsers;} DoS Protected Example (With Pagination): Here, we provide functions that allow the frontend to request users in batches, controlling the gas cost. // DoS Protected: Paginationaddress[] public registeredUsers;function addRegisteredUser(address _user) public { registeredUsers.push(_user);}// Function to get the total count of registered usersfunction getTotalRegisteredUsersCount() public view returns (uint256) { return registeredUsers.length;}// Function to get a paginated list of users// _startIndex: the starting index for the slice// _count: the number of elements to retrieve from the startIndexfunction getPaginatedRegisteredUsers(uint256 _startIndex, uint256 _count) public view returns (address[] memory) { require(_startIndex <= registeredUsers.length, "Start index out of bounds"); uint256 endIndex = _startIndex + _count; if (endIndex > registeredUsers.length) { endIndex = registeredUsers.length; } uint256 actualCount = endIndex - _startIndex; address[] memory result = new address[](actualCount); for (uint256 i = 0; i < actualCount; i++) { result[i] = registeredUsers[_startIndex + i]; } return result;} How a Frontend Would Use It A frontend application (e.g., in React or plain JavaScript) would interact with this paginated contract like this: Get Total Count: First, call getTotalRegisteredUsersCount() to know how many users there are in total. Calculate Pages: Based on the total count, decide how many items to display per page (e.g., 10 or 20). Fetch Pages: Make repeated calls to getPaginatedRegisteredUsers(startIndex, count) as the user navigates through pages. For instance, to get the first 10 users, it would call getPaginatedRegisteredUsers(0, 10); for the next 10, it would call getPaginatedRegisteredUsers(10, 10), and so on. This way, no single transaction tries to fetch all data at once, keeping gas costs manageable and preventing DoS attacks due to excessive computation. 2. Guard Against Unexpected Reverts (External Call DoS) If your contract’s logic depends on the successful execution of an external call (e.g., sending Ether to an address), and that external call can be made to revert by a malicious actor, it can cause a DoS. Vulnerable Example (Auction Refund): Imagine an auction contract that automatically refunds the previous highest bidder when a new higher bid comes in. If the previous highest bidder is a malicious contract that always reverts when it receives Ether, the bid function would always fail, preventing anyone else from bidding. // VULNERABLE: DoS via external call revert address public highestBidder; uint256 public highestBid; function bid() public payable { require(msg.value > highestBid, "Bid must be higher"); if (highestBidder != address(0)) { // If highestBidder is a malicious contract that always reverts on Ether receipt, // this transfer will fail, causing the entire bid function to revert. payable(highestBidder).transfer(highestBid); // Or .send() or .call() } highestBidder = msg.sender; highestBid = msg.value; } Solution: Pull Payment Pattern (as shown above): By using a pull payment system, the contract doesn’t force a transfer to potentially malicious addresses. Users must explicitly call a withdraw function, isolating the failure to their own transaction if they are a malicious contract. 3. Consider Transaction Ordering Dependence (Front-running) While not a direct DoS in the sense of halting a contract, front-running can effectively deny a legitimate user their intended outcome by having a malicious transaction executed before theirs. This is often seen in decentralized exchanges or auction protocols. Scenario: An attacker sees your transaction to buy a rare NFT in the public mempool. They then submit a similar transaction with a higher gas price, ensuring their transaction is mined first, effectively “stealing” the NFT. Mitigation: Commit-Reveal Schemes: For sensitive operations like auctions or votes, users first commit a hashed version of their action, and only later reveal the actual action. This prevents others from knowing their intent beforehand. Time Delays: Implement delays so that sensitive actions can only be executed after a certain number of blocks, giving time for others to react if they see a front-running attempt. Using a Decentralized Sequencer/Relayer: In some Layer 2 solutions, transactions are ordered by a centralized or decentralized sequencer, which can help mitigate front-running risks. 4. Reentrancy Guards (Indirect DoS) While primarily a fund-draining vulnerability, a reentrancy attack can indirectly lead to a DoS if the recursive calls exhaust the gas limit or cause an unexpected state. Protecting against reentrancy is a fundamental security practice. Solution: Checks-Effects-Interactions Pattern: Always update the contract’s state before making any external calls. // Protected with Checks-Effects-Interactions function withdrawSafely() public { uint256 amount = balances[msg.sender]; // Check require(amount > 0, "No funds to withdraw"); balances[msg.sender] = 0; // Effect (update state BEFORE external call) // Interaction (external call) (bool success, ) = payable(msg.sender).call{value: amount}(""); require(success, "Transfer failed"); } Solution: Reentrancy Guard: Use a mutex-like mechanism (e.g., OpenZeppelin’s ReentrancyGuard modifier) to prevent a function from being called again while it's still executing. // SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "@openzeppelin/contracts/security/ReentrancyGuard.sol";contract MyContract is ReentrancyGuard { // Example withdraw function protected against reentrancy attacks function withdraw() public nonReentrant { // withdrawal logic }} Conclusion: Engineering for Uninterrupted Decentralization Protecting your smart contracts from Denial of Service attacks is paramount to building truly reliable and user-friendly decentralized applications. While often overlooked in favor of direct financial security, a successful DoS attack can be just as crippling, effectively locking out users and halting critical operations. By diligently applying strategies such as avoiding unbounded loops, implementing pull payment patterns, considering transaction ordering, and utilizing reentrancy guards, you empower your smart contracts to withstand malicious attempts at disruption. Remember, a resilient smart contract not only secures assets but also guarantees continuous access and functionality, fostering user trust and contributing to a truly robust decentralized future. DoS Protection: Safeguarding Your Contract’s Availability was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story

DoS Protection: Safeguarding Your Contract’s Availability

2025/08/29 00:27

Denial of Service (DoS) attacks pose a critical threat to decentralized applications (dApps). These attacks are not designed to steal funds, but rather to cripple a program’s functionality, making it unusable or inaccessible for legitimate users. This disruption can prevent crucial operations from executing, block user interactions, and severely erode trust in the application. Such incidents effectively “shut down” access, even if underlying assets remain secure. This section will detail common DoS attack methods found in smart contracts and, more importantly, provide robust strategies to defend against them, ensuring your dApps remain resilient and consistently available.

1. Avoid Unbounded Loops

For collections that still need to be iterated (e.g., for data display in a dApp), implementing pagination is crucial to fetch items in smaller, manageable chunks, thus avoiding the block gas limit and potential DoS attacks.

How Pagination Works

Instead of trying to read an entire large array or list from your smart contract in one go (which can exceed the gas limit), pagination allows your frontend application to request data in smaller, defined segments. This distributes the gas cost over multiple, smaller transactions and prevents any single transaction from becoming too expensive.

Examples of Pagination in Solidity

Let’s illustrate with a simple example of a contract storing a list of user addresses.

Vulnerable Example (Without Pagination):

This function tries to return all addresses, which would fail if users array becomes too large.

// VULNERABLE: Trying to return an entire unbounded array
address[] public registeredUsers;
function addRegisteredUser(address _user) public {
registeredUsers.push(_user);
}
// This function will revert if registeredUsers.length is too large
function getAllRegisteredUsers() public view returns (address[] memory) {
return registeredUsers;
}

DoS Protected Example (With Pagination):

Here, we provide functions that allow the frontend to request users in batches, controlling the gas cost.

// DoS Protected: Pagination
address[] public registeredUsers;
function addRegisteredUser(address _user) public {
registeredUsers.push(_user);
}
// Function to get the total count of registered users
function getTotalRegisteredUsersCount() public view returns (uint256) {
return registeredUsers.length;
}
// Function to get a paginated list of users
// _startIndex: the starting index for the slice
// _count: the number of elements to retrieve from the startIndex
function getPaginatedRegisteredUsers(uint256 _startIndex, uint256 _count)
public
view
returns (address[] memory)
{
require(_startIndex <= registeredUsers.length, "Start index out of bounds");
uint256 endIndex = _startIndex + _count;
if (endIndex > registeredUsers.length) {
endIndex = registeredUsers.length;
}
uint256 actualCount = endIndex - _startIndex;
address[] memory result = new address[](actualCount);
for (uint256 i = 0; i < actualCount; i++) {
result[i] = registeredUsers[_startIndex + i];
}
return result;
}

How a Frontend Would Use It

A frontend application (e.g., in React or plain JavaScript) would interact with this paginated contract like this:

  • Get Total Count: First, call getTotalRegisteredUsersCount() to know how many users there are in total.
  • Calculate Pages: Based on the total count, decide how many items to display per page (e.g., 10 or 20).
  • Fetch Pages: Make repeated calls to getPaginatedRegisteredUsers(startIndex, count) as the user navigates through pages. For instance, to get the first 10 users, it would call getPaginatedRegisteredUsers(0, 10); for the next 10, it would call getPaginatedRegisteredUsers(10, 10), and so on.

This way, no single transaction tries to fetch all data at once, keeping gas costs manageable and preventing DoS attacks due to excessive computation.

2. Guard Against Unexpected Reverts (External Call DoS)

If your contract’s logic depends on the successful execution of an external call (e.g., sending Ether to an address), and that external call can be made to revert by a malicious actor, it can cause a DoS.

  • Vulnerable Example (Auction Refund): Imagine an auction contract that automatically refunds the previous highest bidder when a new higher bid comes in. If the previous highest bidder is a malicious contract that always reverts when it receives Ether, the bid function would always fail, preventing anyone else from bidding.
// VULNERABLE: DoS via external call revert 
address public highestBidder; uint256
public highestBid;
function bid() public payable {
require(msg.value > highestBid, "Bid must be higher");
if (highestBidder != address(0)) {
// If highestBidder is a malicious contract that always reverts on Ether receipt,
// this transfer will fail, causing the entire bid function to revert.
payable(highestBidder).transfer(highestBid); // Or .send() or .call()
}
highestBidder = msg.sender;
highestBid = msg.value;
}
  • Solution: Pull Payment Pattern (as shown above): By using a pull payment system, the contract doesn’t force a transfer to potentially malicious addresses. Users must explicitly call a withdraw function, isolating the failure to their own transaction if they are a malicious contract.

3. Consider Transaction Ordering Dependence (Front-running)

While not a direct DoS in the sense of halting a contract, front-running can effectively deny a legitimate user their intended outcome by having a malicious transaction executed before theirs. This is often seen in decentralized exchanges or auction protocols.

  • Scenario: An attacker sees your transaction to buy a rare NFT in the public mempool. They then submit a similar transaction with a higher gas price, ensuring their transaction is mined first, effectively “stealing” the NFT.

Mitigation:

  • Commit-Reveal Schemes: For sensitive operations like auctions or votes, users first commit a hashed version of their action, and only later reveal the actual action. This prevents others from knowing their intent beforehand.
  • Time Delays: Implement delays so that sensitive actions can only be executed after a certain number of blocks, giving time for others to react if they see a front-running attempt.
  • Using a Decentralized Sequencer/Relayer: In some Layer 2 solutions, transactions are ordered by a centralized or decentralized sequencer, which can help mitigate front-running risks.

4. Reentrancy Guards (Indirect DoS)

While primarily a fund-draining vulnerability, a reentrancy attack can indirectly lead to a DoS if the recursive calls exhaust the gas limit or cause an unexpected state. Protecting against reentrancy is a fundamental security practice.

  • Solution: Checks-Effects-Interactions Pattern: Always update the contract’s state before making any external calls.
// Protected with Checks-Effects-Interactions 
function withdrawSafely() public {
uint256 amount = balances[msg.sender]; // Check
require(amount > 0, "No funds to withdraw");
balances[msg.sender] = 0; // Effect (update state BEFORE external call)

// Interaction (external call)
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success, "Transfer failed");
}
  • Solution: Reentrancy Guard: Use a mutex-like mechanism (e.g., OpenZeppelin’s ReentrancyGuard modifier) to prevent a function from being called again while it's still executing.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract MyContract is ReentrancyGuard {

// Example withdraw function protected against reentrancy attacks
function withdraw() public nonReentrant {
// withdrawal logic
}
}

Conclusion: Engineering for Uninterrupted Decentralization

Protecting your smart contracts from Denial of Service attacks is paramount to building truly reliable and user-friendly decentralized applications. While often overlooked in favor of direct financial security, a successful DoS attack can be just as crippling, effectively locking out users and halting critical operations. By diligently applying strategies such as avoiding unbounded loops, implementing pull payment patterns, considering transaction ordering, and utilizing reentrancy guards, you empower your smart contracts to withstand malicious attempts at disruption. Remember, a resilient smart contract not only secures assets but also guarantees continuous access and functionality, fostering user trust and contributing to a truly robust decentralized future.


DoS Protection: Safeguarding Your Contract’s Availability was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.

Disclaimer: The articles reposted on this site are sourced from public platforms and are provided for informational purposes only. They do not necessarily reflect the views of MEXC. All rights remain with the original authors. If you believe any content infringes on third-party rights, please contact service@support.mexc.com for removal. MEXC makes no guarantees regarding the accuracy, completeness, or timeliness of the content and is not responsible for any actions taken based on the information provided. The content does not constitute financial, legal, or other professional advice, nor should it be considered a recommendation or endorsement by MEXC.

You May Also Like

Sunmi Cuts Clutter and Boosts Speed with New All-in-One Mobile Terminal & Scanner-Printer

Sunmi Cuts Clutter and Boosts Speed with New All-in-One Mobile Terminal & Scanner-Printer

SINGAPORE, Jan. 16, 2026 /PRNewswire/ — Business Challenge: Stores today face dual pressures: the need for faster, more flexible customer service beyond fixed counters
Share
AI Journal2026/01/16 20:31
Franklin Templeton CEO Dismisses 50bps Rate Cut Ahead FOMC

Franklin Templeton CEO Dismisses 50bps Rate Cut Ahead FOMC

The post Franklin Templeton CEO Dismisses 50bps Rate Cut Ahead FOMC appeared on BitcoinEthereumNews.com. Franklin Templeton CEO Jenny Johnson has weighed in on whether the Federal Reserve should make a 25 basis points (bps) Fed rate cut or 50 bps cut. This comes ahead of the Fed decision today at today’s FOMC meeting, with the market pricing in a 25 bps cut. Bitcoin and the broader crypto market are currently trading flat ahead of the rate cut decision. Franklin Templeton CEO Weighs In On Potential FOMC Decision In a CNBC interview, Jenny Johnson said that she expects the Fed to make a 25 bps cut today instead of a 50 bps cut. She acknowledged the jobs data, which suggested that the labor market is weakening. However, she noted that this data is backward-looking, indicating that it doesn’t show the current state of the economy. She alluded to the wage growth, which she remarked is an indication of a robust labor market. She added that retail sales are up and that consumers are still spending, despite inflation being sticky at 3%, which makes a case for why the FOMC should opt against a 50-basis-point Fed rate cut. In line with this, the Franklin Templeton CEO said that she would go with a 25 bps rate cut if she were Jerome Powell. She remarked that the Fed still has the October and December FOMC meetings to make further cuts if the incoming data warrants it. Johnson also asserted that the data show a robust economy. However, she noted that there can’t be an argument for no Fed rate cut since Powell already signaled at Jackson Hole that they were likely to lower interest rates at this meeting due to concerns over a weakening labor market. Notably, her comment comes as experts argue for both sides on why the Fed should make a 25 bps cut or…
Share
BitcoinEthereumNews2025/09/18 00:36
State Street Corporation (NYSE: STT) Reports Fourth-Quarter and Full-Year 2025 Financial Results

State Street Corporation (NYSE: STT) Reports Fourth-Quarter and Full-Year 2025 Financial Results

BOSTON–(BUSINESS WIRE)–State Street Corporation (NYSE: STT) reported its fourth-quarter and full-year 2025 financial results today. The news release, presentation
Share
AI Journal2026/01/16 20:46