Security
Smart contract security utilities and implementations
Outdated Version
These contracts aim to cover common security practices.
PullPayment
: A pattern that can be used to avoid reentrancy attacks.ReentrancyGuard
: A modifier that can prevent reentrancy during certain functions.Pausable
: A common emergency response mechanism that can pause functionality while a remediation is pending.
For an overview on reentrancy and the possible mechanisms to prevent it, read our article Reentrancy After Istanbul.
Contracts
import "@openzeppelin/contracts/security/Pausable.sol";
Contract module which allows children to implement an emergency stop mechanism that can be triggered by an authorized account.
This module is used through inheritance. It will make available the
modifiers whenNotPaused
and whenPaused
, which can be applied to
the functions of your contract. Note that they will not be pausable by
simply including this module, only once the modifiers are put in place.
Modifiers
Events
whenNotPaused()
internal
#Modifier to make a function callable only when the contract is not paused.
Requirements:
- The contract must not be paused.
whenPaused()
internal
#Modifier to make a function callable only when the contract is paused.
Requirements:
- The contract must be paused.
constructor()
internal
#Initializes the contract in unpaused state.
paused() → bool
public
#Returns true if the contract is paused, and false otherwise.
_requireNotPaused()
internal
#Throws if the contract is paused.
_requirePaused()
internal
#Throws if the contract is not paused.
_pause()
internal
#Triggers stopped state.
Requirements:
- The contract must not be paused.
_unpause()
internal
#Returns to normal state.
Requirements:
- The contract must be paused.
Paused(address account)
event
#Emitted when the pause is triggered by account
.
Unpaused(address account)
event
#Emitted when the pause is lifted by account
.
import "@openzeppelin/contracts/security/PullPayment.sol";
Simple implementation of a pull-payment strategy, where the paying contract doesn't interact directly with the receiver account, which must withdraw its payments itself.
Pull-payments are often considered the best practice when it comes to sending Ether, security-wise. It prevents recipients from blocking execution, and eliminates reentrancy concerns.
TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post Reentrancy After Istanbul.
To use, derive from the PullPayment
contract, and use PullPayment._asyncTransfer
instead of Solidity's transfer
function. Payees can query their due
payments with PullPayment.payments
, and retrieve them with PullPayment.withdrawPayments
.
constructor()
internal
#withdrawPayments(address payable payee)
public
#Withdraw accumulated payments, forwarding all gas to the recipient.
Note that any account can call this function, not just the payee
.
This means that contracts unaware of the PullPayment
protocol can still
receive funds this way, by having a separate account call
PullPayment.withdrawPayments
.
Forwarding all gas opens the door to reentrancy vulnerabilities.
Make sure you trust the recipient, or are either following the
checks-effects-interactions pattern or using ReentrancyGuard
.
payments(address dest) → uint256
public
#Returns the payments owed to an address.
_asyncTransfer(address dest, uint256 amount)
internal
#Called by the payer to store the sent amount as credit to be pulled.
Funds sent in this way are stored in an intermediate Escrow
contract, so
there is no danger of them being spent before withdrawal.
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
Contract module that helps prevent reentrant calls to a function.
Inheriting from ReentrancyGuard
will make the ReentrancyGuard.nonReentrant
modifier
available, which can be applied to functions to make sure there are no nested
(reentrant) calls to them.
Note that because there is a single nonReentrant
guard, functions marked as
nonReentrant
may not call one another. This can be worked around by making
those functions private
, and then adding external
nonReentrant
entry
points to them.
TIP: If you would like to learn more about reentrancy and alternative ways to protect against it, check out our blog post Reentrancy After Istanbul.
Modifiers
Functions
nonReentrant()
internal
#Prevents a contract from calling itself, directly or indirectly.
Calling a nonReentrant
function from another nonReentrant
function is not supported. It is possible to prevent this from happening
by making the nonReentrant
function external, and making it call a
private
function that does the actual work.
constructor()
internal
#_reentrancyGuardEntered() → bool
internal
#Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
nonReentrant
function in the call stack.