Smart Contract Security: The Power of Pause
Why Think About Smart Contract Security?
Contract code uploaded to a blockchain is immutable, making it impossible to take it offline in the event of a hack. Thorough unit testing and code review are essential, but planning for and implementing security controls on your contract is crucial for any blockchain project. The possibility of an exploit is very real, especially if your DApp becomes popular and more people start to look at your contract code.
When is it Beneficial to Pause a Smart Contract?
Pause capability is one way to protect functions that will be available to all users. A pause modifier or condition can temporarily remove a function’s ability to work, without impacting other contract functions and without opting to destroy the entire contract and start from scratch.
Use Cases for Pause Functionality
- Protecting Critical Functions: Imagine your DApp offers a service to mint an NFT or sell a digital good. The ability to put a temporary hold on these sales or mints may be important to you.
- Initial Coin Offerings (ICOs): When offering a new token to users, you may want to pause the ability of token holders to trade them on an exchange while the initial sale is still underway.
Methods for Implementing Pause Functionality
Global Boolean Variable Method
Declare a global Boolean variable paused
, add this variable with a require
condition in your function, and create a setPaused
function enabling you to change the value.
pragma solidity ^0.8.0;
contract MyContract {
bool public paused;
function myFunction() public {
require(!paused, "Contract is paused");
// function implementation
}
function setPaused(bool _paused) public {
paused = _paused;
}
}
Pausable.sol Method
Use the popular Pausable.sol module from the OpenZeppelin open source smart contract library to standardize pause actions.
pragma solidity ^0.8.0;
import "undefinedgithub.com/OpenZeppelin/openzeppelin-solidity/contracts/security/Pausable.sol";
contract MyContract is Pausable {
function myFunction() public {
require(!paused(), "Contract is paused");
// function implementation
}
}
Global Boolean Variable with Pause Control Method
Add an option to remove pause functionality by creating a Boolean variable canPause
, setting that variable as a condition in your setPause
function, and hardcoding the setting of that variable to false
in a new function that can only be used to remove pause capabilities.
pragma solidity ^0.8.0;
contract MyContract {
bool public paused;
bool public canPause;
function myFunction() public {
require(!paused, "Contract is paused");
// function implementation
}
function setPaused(bool _paused) public {
require(canPause, "Pause functionality is disabled");
paused = _paused;
}
function disablePause() public {
canPause = false;
}
}