Smart contracts have enabled many novel applications, including decentralized finance (DeFi), non-fungible tokens (NFTs), decentralized autonomous organizations (DAOs), and more. But another problem holds back the widespread adoption of smart contracts: poor security. 

Smart contracts live on the blockchain where the code is publicly visible and can be called by anyone (including malicious actors). This means the cost of errors in code is higher, especially as smart contracts often control valuable assets. 

Rigorous testing and code reviews are useful, but cannot eliminate the possibility of smart contract exploits. As a developer, you need a mechanism for responding to vulnerabilities, bugs, and other security incidents. One such feature is the ability to pause smart contract functions. 

Can You Pause a Smart Contract?

Once deployed on the blockchain, a smart contract’s execution cannot be stopped. However, you can implement logic that can temporarily disable the contract’s ability to perform certain actions. 

Benefits of Pausing a Smart Contract 

Pausing a smart contract might seem antithetical to the ethos of decentralization and trustlessness in blockchain technology. Particularly if the power to activate the pause feature suffers from centralized control, users may be wary of using your application. 

But the advantages of pausing a smart contract can outweigh the downsides, especially in cases where the contract controls a considerable amount of funds. These benefits include:

  • Mitigate the impact of exploits on user funds: Pausing critical functions in a contract, such as withdrawals, limits the impact of an attack on users of an application. While it’s possible to analyze the issue and push an upgrade to patch the vulnerability, that’ll only give attackers more time to drain funds from your smart contract. 
  • Mitigate the impact of security issues on users: By blocking calls to specific contract functions, you can work on patching security issues without completely freezing users out of the system. You could even make it such that users can perform certain operations (e.g., withdrawing deposited funds) while other functions remain inaccessible during an emergency. 
  • More flexibility to fixing security issues: Without a pause function, a vulnerable contract might need to be destroyed, while a new instance is deployed on-chain. This can take work and incurs more overhead for developer teams. 

Pausing a smart contract allows you to work on bug fixes without needing to write a new contract from scratch. It also gives more room to focus on fixes without the added pressure of trying to beat attackers to the clock. 

How to Pause Smart Contracts 

The core component of the pause feature is a Boolean flag that indicates whether the contract is paused or not. This value is set to “false” when the contract is created and “true” when the pause feature is activated. 

The other part involved in pausing smart contracts is a function modifier that references the “paused” Boolean variable. A function modifier is paired with a function such that the function executes only if conditions required by the modifier are met. 

When implemented in a contract, the pause feature will ensure that pauseable functions never execute if the contract has been paused. This can be seen in the example below (taken from this guide):

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.1;
contract StartStopUpdateExample {
    address public owner;
    bool public paused;
    constructor() {
        owner = msg.sender;
    }
    function sendMoney() public payable {
    }
    function setPaused(bool _paused) public {
        require(msg.sender == owner, "You are not the owner");
        paused = _paused;
    }
    function withdrawAllMoney(address payable _to) public {
        require(owner == msg.sender, "You cannot withdraw.");
        require(paused == false, "Contract Paused");
        _to.transfer(address(this).balance);
    }
}

This is a simple implementation of an emergency pause functionality with the following details:

1. Paused is a Boolean variable indicating if the contract is in a paused state. (Line #5) 

2. The value of the paused variable can be changed by calling setPaused. (Line #13)

3. To avoid unauthorized access (and prevent malicious attacks), the pause feature can only be activated by the contract’s owner. (Line #14) 

4. The withdrawAllMoney function has a require statement which checks if the contract is paused before execution—calls to withdrawAllMoney will revert or throw an exception if paused evaluates to ‘true’. (Line #15) 

While it is possible to create your pause feature, you can use an existing library, such as OpenZeppelin’s Pauseable.sol, to add emergency pause functionality to your contract. All you have to do is import the contract to inherit the function modifiers:

1. whenNotPaused(): used for functions that should be callable when the contract is not paused. 

2. whenPaused(): used for functions that should be callable when the contract is paused. 

Considerations for Using Pauseable Smart Contracts 

Should you use a pauseable smart contract? The answer depends on different factors, including your project’s security needs and the willingness of users to tolerate administrative controls of a smart contract. If you do implement a pause feature on your smart contract, be transparent with users about it—so they know the risks. You can also avoid the problems of centralization by delegating control of the pause functionality in your contract to a multisignature wallet.

How to Pause a Smart Contract 
Rob Behnke
11.21.2022