Solidity Security By Example #10: Denial of Service With Gas Limit
Originally published in Valix Consulting’s Medium.
Smart contract security is one of the biggest impediments to the mass adoption of the blockchain. For this reason, we are proud to present this series of articles regarding Solidity smart contract security to educate and improve the knowledge in this domain to the public.
Denial of service with gas limit is often caused by a lack of understanding of how the Ethereum Virtual Machine (EVM) works, resulting in the contract being exploited or the contract cannot operate expectedly.
This article will explain how a vulnerable smart contract can be attacked and how to prevent it. Enjoy reading. 😊
You can find all related source code at 👉 https://github.com/serial-coder/solidity-security-by-example/tree/main/10_denial_of_service_with_gas_limit.
The smart contracts in this article are used to demonstrate vulnerability issues only. Some contracts are vulnerable, some are simplified for minimal, some contain malicious code. Hence, do not use the source code in this article in your production.
Nonetheless, feel free to contact Valix Consulting for your smart contract consulting and auditing services. 🕵
Table of Contents
The below code presents the
InsecureNaiveBank contract. This contract simulates a simple (and naive) on-chain banking system in which anyone can deposit their Ether funds to the contract via the
depositFor function (lines 26–36).
The deposited Ethers can be withdrawn anytime by way of executing the
withdraw function (lines 38–44).
The contract also implements the
applyInterest function (lines 46–57) in which a banker can calculate compound interests for all depositors. The interest rate is fixed at 5% (line 4). 💰💰💰
Further, a banker can deposit Ether funds into the contract through the
depositBankFunds function (lines 20–22).
InsecureNaiveBank contract is vulnerable. Can you discover any issues? 👀
We would like to note that the
InsecureNaiveBankcontract got a double spending issue on the
But, it is not in the scope we will focus on in this article. Nevertheless, we will explain that double spending issue in our future article definitely. Please stay tuned!! 🤳
InsecureNaiveBank contract got a design flaw in the
applyInterest function (lines 46–57). Specifically, the
applyInterest function iterates over all depositor accounts (lines 47–56) to calculate compound interest for each depositor (line 52).
However, suppose the number of depositor accounts is too large. In that case, the iteration can consume more gas than the block gas limit, permanently reverting the transaction when a banker calculates depositors’ compound interests. 😧
In other words, the
InsecureNaiveBank contract would incur the unbounded denial-of-service (DoS) issue. Subsequently, the contract could not operate the banking services anymore. 😡
Two situations that can cause the unbounded denial-of-service issue to the
The number of depositor accounts grows over time due to the ordinary adoption
The contract encounters a Sybil attack
Figure 1 below shows how an attacker executes a Sybil attack to freeze the interest calculation service of the
InsecureNaiveBank contract permanently. 😈
The attack is straightforward. An attacker executes the
depositFor function (Steps 1.1 and 1.2) to open a massive number of dummy accounts (Sybil) on the
To open the dummy accounts, the attacker only spends 1 wei for each account.
Once the dummy accounts make the list of depositor accounts too large, a banker’s transaction to invoke the
applyInterest function, for computing all depositors’ compound interests, would be reverted due to exceeding the block gas limit error (Step 2), eternally freezing the interest calculation service. 🤧
The code below presents the
Attack contract that an attacker can use to exploit the
To exploit the
InsecureNaiveBank, an attacker executes the
Attack.openDummyAccounts() function (lines 15–22).
An attacker can specify a large number of dummy accounts (along with supplying 1 wei for each account) they would like to register into the
The result of the attack is shown in Figure 2. As you can see, the attacker could permanently freeze the interest calculation service of the
InsecureNaiveBank contract by performing the Sybil attack.
The cost of the attack was very cheap. The attacker only spent 6,000 wei (+ the transaction gas) to register 6,000 dummy accounts to halt the
InsecureNaiveBank contract’s banking services eternally. ☠️
FixedNaiveBank contract is the improved version of the
InsecureNaiveBank contract. 👨🔧
To remediate the denial-of-service issue on the
applyInterest function, we must redesign how to process the depositors’ interests. In lines 57–77 above, we introduce the
batchApplyInterest function instead.
batchApplyInterest function enables a banker to execute multiple transactions (batch processing) for computing all depositors’ compound interests.
This way, even if the number of depositor accounts is enormous, the interest calculation service of the
FixedNaiveBank contract would no longer be frozen.
Please do not use the
FixedNaiveBankcontract in your production. The
FixedNaiveBankcontract is just a proof of concept of the batch processing but it still implants several security issues.
Even the approaches to calculating the interests, or registering and tracking depositor accounts are still insecure.
In this article, you have learned how the improper design of a smart contract can lead to a denial-of-service (DoS) attack.
You have understood how an attacker exploits the vulnerable contract and how to fix the issue. That’s it for this article. See you in the next article.
Again, you can find all related source code at 👉 https://github.com/serial-coder/solidity-security-by-example/tree/main/10_denial_of_service_with_gas_limit.
Phuwanai Thummavet (serial-coder), Lead Blockchain Security Auditor and Consultant | Blockchain Architect and Developer.
See the author’s profile.
About Valix Consulting
Valix Consulting is a blockchain and smart contract security firm offering a wide range of cybersecurity consulting services. Our specialists, combined with technical expertise, industry knowledge, and support staff, strive to deliver consistently superior quality services.
For any business inquiries, please contact us via Twitter, Facebook, or firstname.lastname@example.org.
Originally published in Valix Consulting’s Medium.