Prechádzať zdrojové kódy

Add ERC20 and ERC777 fixed supply presets #2377 (#2399)

Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
Ashwin Yardi 4 rokov pred
rodič
commit
883116e4af

+ 1 - 0
CHANGELOG.md

@@ -4,6 +4,7 @@
 
  * `BeaconProxy`: added new kind of proxy that allows simultaneous atomic upgrades. ([#2411](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2411))
  * `EIP712`: added helpers to verify EIP712 typed data signatures on chain. ([#2418](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2418))
+ * Presets: added token presets with preminted fixed supply `ERC20PresetFixedSupply` and `ERC777PresetFixedSupply`. ([#2399](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2399))
  * `Address`: added `functionDelegateCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333))
 
 ## 3.3.0 (2020-11-26)

+ 30 - 0
contracts/presets/ERC20PresetFixedSupply.sol

@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.6.2;
+
+import "../token/ERC20/ERC20Burnable.sol";
+
+/**
+ * @dev {ERC20} token, including:
+ *
+ *  - Preminted initial supply
+ *  - Ability for holders to burn (destroy) their tokens
+ *  - No access control mechanism (for minting/pausing) and hence no governance
+ *
+ * This contract uses {ERC20Burnable} to include burn capabilities - head to
+ * its documentation for details.
+ */
+contract ERC20PresetFixedSupply is ERC20Burnable {
+    /**
+     * @dev Mints `initialSupply` amount of token and transfers them to `owner`.  
+     *
+     * See {ERC20-constructor}.
+     */
+    constructor(
+        string memory name,
+        string memory symbol,
+        uint256 initialSupply,
+        address owner
+    ) public ERC20(name, symbol) {
+        _mint(owner, initialSupply);
+    }
+}

+ 27 - 0
contracts/presets/ERC777PresetFixedSupply.sol

@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.6.2;
+
+import "../token/ERC777/ERC777.sol";
+
+/**
+ * @dev {ERC777} token, including:
+ *
+ *  - Preminted initial supply
+ *  - No access control mechanism (for minting/pausing) and hence no governance
+ */
+contract ERC777PresetFixedSupply is ERC777 {
+    /**
+     * @dev Mints `initialSupply` amount of token and transfers them to `owner`.  
+     *
+     * See {ERC777-constructor}.
+     */
+    constructor(
+        string memory name,
+        string memory symbol,
+        address[] memory defaultOperators,
+        uint256 initialSupply,
+        address owner
+    ) public ERC777(name, symbol, defaultOperators) {
+        _mint(owner, initialSupply, "", "");
+    }
+}

+ 4 - 0
contracts/presets/README.adoc

@@ -16,3 +16,7 @@ TIP: Intermediate and advanced users can use these as starting points when writi
 {{ERC721PresetMinterPauserAutoId}}
 
 {{ERC1155PresetMinterPauser}}
+
+{{ERC20PresetFixedSupply}}
+
+{{ERC777PresetFixedSupply}}

+ 42 - 0
test/presets/ERC20PresetFixedSupply.test.js

@@ -0,0 +1,42 @@
+const { BN, constants, expectEvent } = require('@openzeppelin/test-helpers');
+const { ZERO_ADDRESS } = constants;
+
+const { expect } = require('chai');
+
+const ERC20PresetFixedSupply = artifacts.require('ERC20PresetFixedSupply');
+
+contract('ERC20PresetFixedSupply', function (accounts) {
+  const [deployer, owner] = accounts;
+
+  const name = 'PresetFixedSupply';
+  const symbol = 'PFS';
+
+  const initialSupply = new BN('50000');
+  const amount = new BN('10000');
+
+  before(async function () {
+    this.token = await ERC20PresetFixedSupply.new(name, symbol, initialSupply, owner, { from: deployer });
+  });
+
+  it('deployer has the balance equal to initial supply', async function () {
+    expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(initialSupply);
+  });
+
+  it('total supply is equal to initial supply', async function () {
+    expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply);
+  });
+
+  describe('burning', function () {
+    it('holders can burn their tokens', async function () {
+      const remainingBalance = initialSupply.sub(amount);
+      const receipt = await this.token.burn(amount, { from: owner });
+      expectEvent(receipt, 'Transfer', { from: owner, to: ZERO_ADDRESS, value: amount });
+      expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(remainingBalance);
+    });
+
+    it('decrements totalSupply', async function () {
+      const expectedSupply = initialSupply.sub(amount);
+      expect(await this.token.totalSupply()).to.be.bignumber.equal(expectedSupply);
+    });
+  });
+});

+ 49 - 0
test/presets/ERC777PresetFixedSupply.test.js

@@ -0,0 +1,49 @@
+const { BN, singletons } = require('@openzeppelin/test-helpers');
+
+const { expect } = require('chai');
+
+const ERC777PresetFixedSupply = artifacts.require('ERC777PresetFixedSupply');
+
+contract('ERC777PresetFixedSupply', function (accounts) {
+  const [registryFunder, owner, defaultOperatorA, defaultOperatorB, anyone] = accounts;
+
+  const initialSupply = new BN('10000');
+  const name = 'ERC777Preset';
+  const symbol = '777P';
+
+  const defaultOperators = [defaultOperatorA, defaultOperatorB];
+
+  before(async function () {
+    await singletons.ERC1820Registry(registryFunder);
+  });
+
+  beforeEach(async function () {
+    this.token = await ERC777PresetFixedSupply.new(name, symbol, defaultOperators, initialSupply, owner);
+  });
+
+  it('returns the name', async function () {
+    expect(await this.token.name()).to.equal(name);
+  });
+
+  it('returns the symbol', async function () {
+    expect(await this.token.symbol()).to.equal(symbol);
+  });
+
+  it('returns the default operators', async function () {
+    expect(await this.token.defaultOperators()).to.deep.equal(defaultOperators);
+  });
+
+  it('default operators are operators for all accounts', async function () {
+    for (const operator of defaultOperators) {
+      expect(await this.token.isOperatorFor(operator, anyone)).to.equal(true);
+    }
+  });
+
+  it('returns the total supply equal to initial supply', async function () {
+    expect(await this.token.totalSupply()).to.be.bignumber.equal(initialSupply);
+  });
+
+  it('returns the balance of owner equal to initial supply', async function () {
+    expect(await this.token.balanceOf(owner)).to.be.bignumber.equal(initialSupply);
+  });
+});