فهرست منبع

Add missing hook to ERC777, fix relevant documentation (#2191)

* Improve ERC20/721 Pausable docs

* Add ERC20Pausable mint and burn tests

* Add ERC721Pausable mint and burn tests

* Add _beforeTransfer hook in ERC777 to mint and burn
Nicolás Venturo 5 سال پیش
والد
کامیت
3e139baa50

+ 8 - 0
contracts/mocks/ERC20PausableMock.sol

@@ -20,4 +20,12 @@ contract ERC20PausableMock is ERC20Pausable {
     function unpause() external {
         _unpause();
     }
+
+    function mint(address to, uint256 amount) public {
+        _mint(to, amount);
+    }
+
+    function burn(address from, uint256 amount) public {
+        _burn(from, amount);
+    }
 }

+ 1 - 2
contracts/token/ERC20/ERC20Pausable.sol

@@ -4,8 +4,7 @@ import "./ERC20.sol";
 import "../../utils/Pausable.sol";
 
 /**
- * @title Pausable token
- * @dev ERC20 with pausable transfers and allowances.
+ * @dev ERC20 token with pausable token transfers, minting and burning.
  *
  * Useful for scenarios such as preventing trades until the end of an evaluation
  * period, or having an emergency switch for freezing all token transfers in the

+ 12 - 2
contracts/token/ERC721/ERC721Pausable.sol

@@ -4,10 +4,20 @@ import "./ERC721.sol";
 import "../../utils/Pausable.sol";
 
 /**
- * @title ERC721 Non-Fungible Pausable token
- * @dev ERC721 modified with pausable transfers.
+ * @dev ERC721 token with pausable token transfers, minting and burning.
+ *
+ * Useful for scenarios such as preventing trades until the end of an evaluation
+ * period, or having an emergency switch for freezing all token transfers in the
+ * event of a large bug.
  */
 abstract contract ERC721Pausable is ERC721, Pausable {
+    /**
+     * @dev See {ERC721-_beforeTokenTransfer}.
+     *
+     * Requirements:
+     *
+     * - the contract must not be paused.
+     */
     function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
         super._beforeTokenTransfer(from, to, tokenId);
 

+ 4 - 0
contracts/token/ERC777/ERC777.sol

@@ -322,6 +322,8 @@ contract ERC777 is Context, IERC777, IERC20 {
 
         address operator = _msgSender();
 
+        _beforeTokenTransfer(operator, address(0), account, amount);
+
         // Update state variables
         _totalSupply = _totalSupply.add(amount);
         _balances[account] = _balances[account].add(amount);
@@ -382,6 +384,8 @@ contract ERC777 is Context, IERC777, IERC20 {
 
         address operator = _msgSender();
 
+        _beforeTokenTransfer(operator, from, address(0), amount);
+
         _callTokensToSend(operator, from, address(0), amount, data, operatorData);
 
         // Update state variables

+ 54 - 0
test/token/ERC20/ERC20Pausable.test.js

@@ -78,5 +78,59 @@ describe('ERC20Pausable', function () {
         );
       });
     });
+
+    describe('mint', function () {
+      const amount = new BN('42');
+
+      it('allows to mint when unpaused', async function () {
+        await this.token.mint(recipient, amount);
+
+        expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount);
+      });
+
+      it('allows to mint when paused and then unpaused', async function () {
+        await this.token.pause();
+        await this.token.unpause();
+
+        await this.token.mint(recipient, amount);
+
+        expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount);
+      });
+
+      it('reverts when trying to mint when paused', async function () {
+        await this.token.pause();
+
+        await expectRevert(this.token.mint(recipient, amount),
+          'ERC20Pausable: token transfer while paused'
+        );
+      });
+    });
+
+    describe('burn', function () {
+      const amount = new BN('42');
+
+      it('allows to burn when unpaused', async function () {
+        await this.token.burn(holder, amount);
+
+        expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(amount));
+      });
+
+      it('allows to burn when paused and then unpaused', async function () {
+        await this.token.pause();
+        await this.token.unpause();
+
+        await this.token.burn(holder, amount);
+
+        expect(await this.token.balanceOf(holder)).to.be.bignumber.equal(initialSupply.sub(amount));
+      });
+
+      it('reverts when trying to burn when paused', async function () {
+        await this.token.pause();
+
+        await expectRevert(this.token.burn(holder, amount),
+          'ERC20Pausable: token transfer while paused'
+        );
+      });
+    });
   });
 });

+ 17 - 2
test/token/ERC721/ERC721Pausable.test.js

@@ -19,7 +19,8 @@ describe('ERC721Pausable', function () {
 
   context('when token is paused', function () {
     const firstTokenId = new BN(1);
-    const mintedTokens = new BN(1);
+    const secondTokenId = new BN(1337);
+
     const mockData = '0x42';
 
     beforeEach(async function () {
@@ -49,6 +50,20 @@ describe('ERC721Pausable', function () {
       );
     });
 
+    it('reverts when trying to mint', async function () {
+      await expectRevert(
+        this.token.mint(receiver, secondTokenId),
+        'ERC721Pausable: token transfer while paused'
+      );
+    });
+
+    it('reverts when trying to burn', async function () {
+      await expectRevert(
+        this.token.burn(firstTokenId),
+        'ERC721Pausable: token transfer while paused'
+      );
+    });
+
     describe('getApproved', function () {
       it('returns approved address', async function () {
         const approvedAccount = await this.token.getApproved(firstTokenId);
@@ -59,7 +74,7 @@ describe('ERC721Pausable', function () {
     describe('balanceOf', function () {
       it('returns the amount of tokens owned by the given address', async function () {
         const balance = await this.token.balanceOf(owner);
-        expect(balance).to.be.bignumber.equal(mintedTokens);
+        expect(balance).to.be.bignumber.equal('1');
       });
     });