OpenZeppelin Contracts v2.4

We’ve recently released version 2.4 of the OpenZeppelin Contracts library, featuring support for seamless user onboarding via the Gas Station Network, and utilities reflecting the latest security best practices, in preparation for the upcoming Istanbul hardfork. Strap in!

The Gas Station Network (GSN): fixing user onboarding :fuelpump:

2019 saw the rise of meta-transaction solutions and industry-wide efforts such as the MetaCartel to improve adoption of web3 applications by bringing their user experience more in-line with regular everyday webapps. The Gas Station Network is the result of collaboration of the GSN Alliance, a group of companies of which OpenZeppelin is part of.

In a nutshell, the GSN lets users interact with web3 applications without having to ever hold Ether :scream_cat:. Not only does this mean that MetaMask is no longer mandatory, but also that users don’t have to go through the grueling process of procuring Ether before they can actually use the application.

Version 2.4 includes first-class support for the GSN in all of the OpenZeppelin contracts: by simply inheriting from the GSNRecipient contract, all functions will be able to be called without the user having to pay for gas. By mixing GSNRecipient and long-standing contracts such as ERC20 or ERC721, you can create a gas-less token in under a minute! :sparkles:

While there are some details that you need to be aware of when dealing with the GSN, we’ve wrote multiple guides and tutorials to help you get up to speed quickly: the GSN Starting Guide will tell you everything you need you know regarding development, testing, and interaction with GSN-capable contracts. Go check it out!

transfer considered harmful :no_entry_sign:

The upcoming Istanbul hardfork (scheduled for late 2019/early 2020) will reprice certain opcodes, breaking many contracts that are running on mainnet today. Much has been discussed in different security-oriented Ethereum channels, and one of the takeaways is that relying on Solidity’s transfer function to send Ether is often a mistake that will lead to applications being irreversibly broken in the future. You can read more about this in Consensys Dilligence’s article suggesting dropping transfer immediately, and our own analysis of how the hardfork will cause issues with OpenZeppelin upgradeable contracts.

transfer is, however, a superior option to the native alternatives, call and send, which can be easily misused and lead to security vulnerabilities. Because of this, we’ve created sendValue, a drop-in replacement for transfer:

pragma solidity ^0.5.5;

import "@openzeppelin/contracts/utils/Address.sol";

contract MyContract {
    using Address for address payable;

    function wrong(address payable receiver, uint256 amount) external {
        receiver.transfer(amount); // do not use!
    }

    function right(address payable receiver, uint256 amount) external {
        receiver.sendValue(amount); // use sendValue instead of transfer
    }
}

The only difference between sendValue and transfer is that sendValue will forward all gas to the recipient, Because of this, saying goodbye to transfer also means having to be more aware of possible reentrancy vulnerabilities your contract might have. We will be publishing guides on how to deal with these and stay safe soon, but in the meantime, consider using our ReentrancyGuard and PullPayment contracts.

Better error messages

Often, SafeMath is used to e.g. check that a user transferring tokens has enough balance via balances[user].sub(amount). An unfortunate side effect of this is that, on reverts, the error message you’ll get will come from SafeMath itself instead of the token, making debugging harder. We can do better.

We’ve now added variants to sub, div and mod that let you specify custom error messages, greatly improving the development experience. Additionally, we’ve retrofitted our contracts with these new helpers to improve our own errors, so instead of ERC20.transfer emitting SafeMath: subtraction overflow, you’ll now get a much clearer ERC20: transfer amount exceeds balance message. Yay easier debugging! :confetti_ball:

Better documentation :open_book:

We’re constantly improving our documentation site, making sure all information you need to safely develop your smart contract application is available in a clear and concise manner. A special thanks to all the open source contributors that are constantly opening PR with fixes and suggestions! :raised_hands:

Changelog

As always, we also provide a detailed changelog with all new features, breaking changes, etc. Take a look!

7 Likes

There is another way of doing transfers of ETH without reentrancy risks, the SELFDESTRUCT opcode could be used, with something like this:

library Address {
    function sendValue(address _to, uint256 _val) internal {
        bytes memory code = abi.encodePacked(hex"73", _to, hex"FF");

        assembly {
            pop(
                create(
                    _val,
                    add(code, 0x20),
                    mload(code)
                )
            )
        }
    }
}

With a cost of 5000 GAS, it would be more expensive than using the ReentrancyGuard util (only after Istambul). Also, the SELFDETRUCT method doesn’t revert if the account receiving the ETH is a contract and it doesn’t implements a fallback method.

1 Like

Interesting! I had not considered that approach. However, you’d lose the ability for the recipient address to react to the funds sent, which is often a desirable property since it leads to composability. To be frank, I’m not a fan of selfdestruct being able to bypass this.

2 Likes

I’ve fallen foul of that, so the SafeMath error improvements is very welcome…

1 Like