Simple ERC777 token example

OpenZeppelin 2.3.0 release candidate includes an implementation of ERC777.

I created a simple ERC777 token inheriting from the OpenZeppelin implementation, based on the SimpleToken example.

A key point to note is that in a testing environment an ERC777 token requires deploying an ERC1820 registry using openzeppelin-test-helpers. (Thanks @frangio)

This example smart contract merely sets a name, symbol and has no default operators. All tokens are pre-assigned to the creator using the internal mint function. Based on SimpleToken.sol

Smart Contract

pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/token/ERC777/ERC777.sol";


/**
 * @title Simple777Token
 * @dev Very simple ERC777 Token example, where all tokens are pre-assigned to the creator.
 * Note they can later distribute these tokens as they wish using `transfer` and other
 * `ERC20` or `ERC777` functions.
 * Based on https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/examples/SimpleToken.sol
 */
contract Simple777Token is ERC777 {

    /**
     * @dev Constructor that gives msg.sender all of existing tokens.
     */
    constructor () public ERC777("Simple777Token", "S7", new address[](0)) {
        _mint(msg.sender, msg.sender, 10000 * 10 ** 18, "", "");
    }
}

Migration

const Simple777Token = artifacts.require('Simple777Token');

require('openzeppelin-test-helpers/configure')({ web3 });

const { singletons } = require('openzeppelin-test-helpers');

module.exports = async function (deployer, network, accounts) {
  if (network === 'development') {
    // In a test environment an ERC777 token requires deploying an ERC1820 registry
    await singletons.ERC1820Registry(accounts[0]);
  }

  await deployer.deploy(Simple777Token);
};

Test

Tests are based on SimpleToken.test.js

// Based on https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/test/examples/SimpleToken.test.js
const { expectEvent, singletons, constants } = require('openzeppelin-test-helpers');
const { ZERO_ADDRESS } = constants;

const Simple777Token = artifacts.require('Simple777Token');

contract('Simple777Token', function ([_, registryFunder, creator]) {
  beforeEach(async function () {
    this.erc1820 = await singletons.ERC1820Registry(registryFunder);
    this.token = await Simple777Token.new({ from: creator });
  });

  it('has a name', async function () {
    (await this.token.name()).should.equal('Simple777Token');
  });

  it('has a symbol', async function () {
    (await this.token.symbol()).should.equal('S7');
  });

  it('assigns the initial total supply to the creator', async function () {
    const totalSupply = await this.token.totalSupply();
    const creatorBalance = await this.token.balanceOf(creator);

    creatorBalance.should.be.bignumber.equal(totalSupply);

    await expectEvent.inConstruction(this.token, 'Transfer', {
      from: ZERO_ADDRESS,
      to: creator,
      value: totalSupply,
    });
  });
});

I have deployed to ganache-cli and Ropsten and Rinkeby.

The Simple ERC777 token example can be found on GitHub.

3 Likes

This is great, thanks for sharing it!

1 Like

Documentation for the OpenZeppelin ERC777 implementation:

@abcoathup what if we move this to the #general:guides-and-tutorials category? :slight_smile:

1 Like