Skip to content

Commit

Permalink
Bundle ERC20Detailed (#2161)
Browse files Browse the repository at this point in the history
* Merge ERC20Detailed into ERC20, make derived contracts abstract

* Fix Create2 tests

* Fix failing test

* Default decimals to 18

* Add tests for setupDecimals

* Add changelog entry

* Update CHANGELOG.md

* Update CHANGELOG.md

* Replace isConstructor for !isContract

* Update CHANGELOG.md

Co-Authored-By: Francisco Giordano <frangio.1@gmail.com>

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
  • Loading branch information
nventuro and frangio authored Apr 2, 2020
1 parent 5b5d91c commit 0408e51
Show file tree
Hide file tree
Showing 25 changed files with 192 additions and 135 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
* `ERC777`: removed `_callsTokensToSend` and `_callTokensReceived`. ([#2134](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2134))
* `EnumerableSet`: renamed `get` to `at`. ([#2151](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2151))
* `ERC165Checker`: functions no longer have a leading underscore. ([#2150](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2150))
* `ERC20Detailed`: this contract was removed and its functionality merged into `ERC20`. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161))
* `ERC20`: added a constructor for `name` and `symbol`. `decimals` now defaults to 18. ([#2161](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2161))

## 2.5.0 (2020-02-04)

Expand Down
11 changes: 5 additions & 6 deletions contracts/GSN/GSNRecipientERC20Fee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import "../math/SafeMath.sol";
import "../access/Ownable.sol";
import "../token/ERC20/SafeERC20.sol";
import "../token/ERC20/ERC20.sol";
import "../token/ERC20/ERC20Detailed.sol";

/**
* @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that charges transaction fees in a special purpose ERC20
Expand All @@ -30,7 +29,7 @@ contract GSNRecipientERC20Fee is GSNRecipient {
* @dev The arguments to the constructor are the details that the gas payment token will have: `name` and `symbol`. `decimals` is hard-coded to 18.
*/
constructor(string memory name, string memory symbol) public {
_token = new __unstable__ERC20Owned(name, symbol, 18);
_token = new __unstable__ERC20Owned(name, symbol);
}

/**
Expand Down Expand Up @@ -112,18 +111,18 @@ contract GSNRecipientERC20Fee is GSNRecipient {
* outside of this context.
*/
// solhint-disable-next-line contract-name-camelcase
contract __unstable__ERC20Owned is ERC20, ERC20Detailed, Ownable {
contract __unstable__ERC20Owned is ERC20, Ownable {
uint256 private constant _UINT256_MAX = 2**256 - 1;

constructor(string memory name, string memory symbol, uint8 decimals) public ERC20Detailed(name, symbol, decimals) { }
constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }

// The owner (GSNRecipientERC20Fee) can mint tokens
function mint(address account, uint256 amount) public onlyOwner {
_mint(account, amount);
}

// The owner has 'infinite' allowance for all token holders
function allowance(address tokenOwner, address spender) public view override(ERC20, IERC20) returns (uint256) {
function allowance(address tokenOwner, address spender) public view override returns (uint256) {
if (spender == owner()) {
return _UINT256_MAX;
} else {
Expand All @@ -140,7 +139,7 @@ contract __unstable__ERC20Owned is ERC20, ERC20Detailed, Ownable {
}
}

function transferFrom(address sender, address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool) {
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
if (recipient == owner()) {
_transfer(sender, recipient, amount);
return true;
Expand Down
6 changes: 3 additions & 3 deletions contracts/mocks/Create2Impl.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
pragma solidity ^0.6.0;

import "../utils/Create2.sol";
import "../token/ERC20/ERC20.sol";
import "../introspection/ERC1820Implementer.sol";

contract Create2Impl {
function deploy(uint256 value, bytes32 salt, bytes memory code) public {
Create2.deploy(value, salt, code);
}

function deployERC20(uint256 value, bytes32 salt) public {
function deployERC1820Implementer(uint256 value, bytes32 salt) public {
// solhint-disable-next-line indent
Create2.deploy(value, salt, type(ERC20).creationCode);
Create2.deploy(value, salt, type(ERC1820Implementer).creationCode);
}

function computeAddress(bytes32 salt, bytes32 codeHash) public view returns (address) {
Expand Down
7 changes: 6 additions & 1 deletion contracts/mocks/ERC20BurnableMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ pragma solidity ^0.6.0;
import "../token/ERC20/ERC20Burnable.sol";

contract ERC20BurnableMock is ERC20Burnable {
constructor (address initialAccount, uint256 initialBalance) public {
constructor (
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) public ERC20(name, symbol) {
_mint(initialAccount, initialBalance);
}
}
4 changes: 3 additions & 1 deletion contracts/mocks/ERC20CappedMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ pragma solidity ^0.6.0;
import "../token/ERC20/ERC20Capped.sol";

contract ERC20CappedMock is ERC20Capped {
constructor (uint256 cap) public ERC20Capped(cap) { }
constructor (string memory name, string memory symbol, uint256 cap)
public ERC20(name, symbol) ERC20Capped(cap)
{ }

function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);
Expand Down
13 changes: 13 additions & 0 deletions contracts/mocks/ERC20DecimalsMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pragma solidity ^0.6.0;

import "../token/ERC20/ERC20.sol";

contract ERC20DecimalsMock is ERC20 {
constructor (string memory name, string memory symbol, uint8 decimals) public ERC20(name, symbol) {
_setupDecimals(decimals);
}

function setupDecimals(uint8 decimals) public {
_setupDecimals(decimals);
}
}
13 changes: 0 additions & 13 deletions contracts/mocks/ERC20DetailedMock.sol

This file was deleted.

7 changes: 6 additions & 1 deletion contracts/mocks/ERC20Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import "../token/ERC20/ERC20.sol";

// mock class using ERC20
contract ERC20Mock is ERC20 {
constructor (address initialAccount, uint256 initialBalance) public payable {
constructor (
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) public payable ERC20(name, symbol) {
_mint(initialAccount, initialBalance);
}

Expand Down
7 changes: 6 additions & 1 deletion contracts/mocks/ERC20PausableMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import "../token/ERC20/ERC20Pausable.sol";

// mock class using ERC20Pausable
contract ERC20PausableMock is ERC20Pausable {
constructor (address initialAccount, uint256 initialBalance) public {
constructor (
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) public ERC20(name, symbol) {
_mint(initialAccount, initialBalance);
}

Expand Down
7 changes: 6 additions & 1 deletion contracts/mocks/ERC20SnapshotMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import "../token/ERC20/ERC20Snapshot.sol";


contract ERC20SnapshotMock is ERC20Snapshot {
constructor(address initialAccount, uint256 initialBalance) public {
constructor(
string memory name,
string memory symbol,
address initialAccount,
uint256 initialBalance
) public ERC20(name, symbol) {
_mint(initialAccount, initialBalance);
}

Expand Down
65 changes: 65 additions & 0 deletions contracts/token/ERC20/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.6.0;
import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
* @dev Implementation of the {IERC20} interface.
Expand Down Expand Up @@ -30,13 +31,65 @@ import "../../math/SafeMath.sol";
*/
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
using Address for address;

mapping (address => uint256) private _balances;

mapping (address => mapping (address => uint256)) private _allowances;

uint256 private _totalSupply;

string private _name;
string private _symbol;
uint8 private _decimals;

/**
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
_decimals = 18;
}

/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}

/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view returns (string memory) {
return _symbol;
}

/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5,05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
* called.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view returns (uint8) {
return _decimals;
}

/**
* @dev See {IERC20-totalSupply}.
*/
Expand Down Expand Up @@ -223,6 +276,18 @@ contract ERC20 is Context, IERC20 {
emit Approval(owner, spender, amount);
}

/**
* @dev Sets {decimals} to a value other than the default one of 18.
*
* Requirements:
*
* - this function can only be called from a constructor.
*/
function _setupDecimals(uint8 decimals_) internal {
require(!address(this).isContract(), "ERC20: decimals cannot be changed after construction");
_decimals = decimals_;
}

/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
Expand Down
2 changes: 1 addition & 1 deletion contracts/token/ERC20/ERC20Burnable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "./ERC20.sol";
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
contract ERC20Burnable is Context, ERC20 {
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @dev Destroys `amount` tokens from the caller.
*
Expand Down
2 changes: 1 addition & 1 deletion contracts/token/ERC20/ERC20Capped.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "./ERC20.sol";
/**
* @dev Extension of {ERC20} that adds a cap to the supply of tokens.
*/
contract ERC20Capped is ERC20 {
abstract contract ERC20Capped is ERC20 {
uint256 private _cap;

/**
Expand Down
54 changes: 0 additions & 54 deletions contracts/token/ERC20/ERC20Detailed.sol

This file was deleted.

2 changes: 1 addition & 1 deletion contracts/token/ERC20/ERC20Pausable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import "../../utils/Pausable.sol";
* period, or having an emergency switch for freezing all token transfers in the
* event of a large bug.
*/
contract ERC20Pausable is ERC20, Pausable {
abstract contract ERC20Pausable is ERC20, Pausable {
/**
* @dev See {ERC20-_beforeTokenTransfer}.
*
Expand Down
2 changes: 1 addition & 1 deletion contracts/token/ERC20/ERC20Snapshot.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import "./ERC20.sol";
* account address.
* @author Validity Labs AG <info@validitylabs.org>
*/
contract ERC20Snapshot is ERC20 {
abstract contract ERC20Snapshot is ERC20 {
// Inspired by Jordi Baylina's MiniMeToken to record historical balances:
// https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol

Expand Down
4 changes: 2 additions & 2 deletions test/GSN/GSNRecipientERC20Fee.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const gsn = require('@openzeppelin/gsn-helpers');
const { expect } = require('chai');

const GSNRecipientERC20FeeMock = contract.fromArtifact('GSNRecipientERC20FeeMock');
const ERC20Detailed = contract.fromArtifact('ERC20Detailed');
const ERC20 = contract.fromArtifact('ERC20');
const IRelayHub = contract.fromArtifact('IRelayHub');

describe('GSNRecipientERC20Fee', function () {
Expand All @@ -17,7 +17,7 @@ describe('GSNRecipientERC20Fee', function () {

beforeEach(async function () {
this.recipient = await GSNRecipientERC20FeeMock.new(name, symbol);
this.token = await ERC20Detailed.at(await this.recipient.token());
this.token = await ERC20.at(await this.recipient.token());
});

describe('token', function () {
Expand Down
Loading

0 comments on commit 0408e51

Please sign in to comment.