EVM Package examples (#32)
* Added StandardToken (on-chain lib) * Added OnChainERC20 example. * Added OnChainERC721 * Update OnChainERC721.test.js * Renamed the contracts to Standalone*. * Fix path to Initializable in StandardToken example
This commit is contained in:
committed by
Santiago Palladino
parent
6395ddac2c
commit
5e69036bbc
60
contracts/examples/StandaloneERC20.sol
Normal file
60
contracts/examples/StandaloneERC20.sol
Normal file
@ -0,0 +1,60 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "zos-lib/contracts/Initializable.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Standard ERC20 token, with minting and pause functionality.
|
||||
*
|
||||
*/
|
||||
contract StandaloneERC20 is Initializable, ERC20Detailed, ERC20Mintable, ERC20Pausable {
|
||||
function initialize(string name, string symbol, uint8 decimals, uint256 initialSupply, address initialHolder, address[] minters, address[] pausers) public initializer {
|
||||
require(initialSupply > 0);
|
||||
|
||||
ERC20Detailed.initialize(name, symbol, decimals);
|
||||
|
||||
// Mint the initial supply
|
||||
_mint(initialHolder, initialSupply);
|
||||
|
||||
// Initialize the minter and pauser roles, and renounce them
|
||||
ERC20Mintable.initialize(address(this));
|
||||
renounceMinter();
|
||||
|
||||
ERC20Pausable.initialize(address(this));
|
||||
renouncePauser();
|
||||
|
||||
// Add the requested minters and pausers (this can be done after renouncing since
|
||||
// these are the internal calls)
|
||||
for (uint256 i = 0; i < minters.length; ++i) {
|
||||
_addMinter(minters[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pausers.length; ++i) {
|
||||
_addPauser(pausers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function initialize(string name, string symbol, uint8 decimals, address[] minters, address[] pausers) public initializer {
|
||||
ERC20Detailed.initialize(name, symbol, decimals);
|
||||
|
||||
// Initialize the minter and pauser roles, and renounce them
|
||||
ERC20Mintable.initialize(address(this));
|
||||
renounceMinter();
|
||||
|
||||
ERC20Pausable.initialize(address(this));
|
||||
renouncePauser();
|
||||
|
||||
// Add the requested minters and pausers (this can be done after renouncing since
|
||||
// these are the internal calls)
|
||||
for (uint256 i = 0; i < minters.length; ++i) {
|
||||
_addMinter(minters[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pausers.length; ++i) {
|
||||
_addPauser(pausers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
contracts/examples/StandaloneERC721.sol
Normal file
38
contracts/examples/StandaloneERC721.sol
Normal file
@ -0,0 +1,38 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "zos-lib/contracts/Initializable.sol";
|
||||
import "../token/ERC721/ERC721.sol";
|
||||
import "../token/ERC721/ERC721Enumerable.sol";
|
||||
import "../token/ERC721/ERC721Metadata.sol";
|
||||
import "../token/ERC721/ERC721MetadataMintable.sol";
|
||||
import "../token/ERC721/ERC721Pausable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Standard ERC721 token, with minting and pause functionality.
|
||||
*
|
||||
*/
|
||||
contract StandaloneERC721 is Initializable, ERC721, ERC721Enumerable, ERC721Metadata, ERC721MetadataMintable, ERC721Pausable {
|
||||
function initialize(string name, string symbol, address[] minters, address[] pausers) public initializer {
|
||||
ERC721.initialize();
|
||||
ERC721Enumerable.initialize();
|
||||
ERC721Metadata.initialize(name, symbol);
|
||||
|
||||
// Initialize the minter and pauser roles, and renounce them
|
||||
ERC721MetadataMintable.initialize(address(this));
|
||||
renounceMinter();
|
||||
|
||||
ERC721Pausable.initialize(address(this));
|
||||
renouncePauser();
|
||||
|
||||
// Add the requested minters and pausers (this can be done after renouncing since
|
||||
// these are the internal calls)
|
||||
for (uint256 i = 0; i < minters.length; ++i) {
|
||||
_addMinter(minters[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pausers.length; ++i) {
|
||||
_addPauser(pausers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
contracts/examples/StandardToken.sol
Normal file
39
contracts/examples/StandardToken.sol
Normal file
@ -0,0 +1,39 @@
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
import "zos-lib/contracts/Initializable.sol";
|
||||
import "../token/ERC20/ERC20Detailed.sol";
|
||||
import "../token/ERC20/ERC20Mintable.sol";
|
||||
import "../token/ERC20/ERC20Pausable.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @title Standard ERC20 token, with minting and pause functionality.
|
||||
*
|
||||
*/
|
||||
contract StandardToken is Initializable, ERC20Detailed, ERC20Mintable, ERC20Pausable {
|
||||
function initialize(string name, string symbol, uint8 decimals, uint256 initialSupply, address initialHolder, address[] minters, address[] pausers) public initializer {
|
||||
ERC20Detailed.initialize(name, symbol, decimals);
|
||||
|
||||
// Mint the initial supply
|
||||
if (initialSupply > 0) { // To allow passing a null address when not doing any initial supply
|
||||
_mint(initialHolder, initialSupply);
|
||||
}
|
||||
|
||||
// Initialize the minter and pauser roles, and renounce them
|
||||
ERC20Mintable.initialize(address(this));
|
||||
renounceMinter();
|
||||
|
||||
ERC20Pausable.initialize(address(this));
|
||||
renouncePauser();
|
||||
|
||||
// Add the requested minters and pausers (this can be done after renouncing since
|
||||
// these are the internal calls)
|
||||
for (uint256 i = 0; i < minters.length; ++i) {
|
||||
_addMinter(minters[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < pausers.length; ++i) {
|
||||
_addPauser(pausers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
158
test/examples/StandaloneERC20.test.js
Normal file
158
test/examples/StandaloneERC20.test.js
Normal file
@ -0,0 +1,158 @@
|
||||
const encodeCall = require('zos-lib/lib/helpers/encodeCall').default;
|
||||
const { shouldBehaveLikeERC20Mintable } = require('../token/ERC20/behaviors/ERC20Mintable.behavior');
|
||||
const { assertRevert } = require('../helpers/assertRevert');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
const should = require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
const StandaloneERC20 = artifacts.require('StandaloneERC20');
|
||||
|
||||
contract('StandaloneERC20', function ([_, deployer, initialHolder, minterA, minterB, pauserA, pauserB, anyone, ...otherAccounts]) {
|
||||
const name = "StandaloneERC20";
|
||||
const symbol = "SAERC20";
|
||||
const decimals = 18;
|
||||
|
||||
const initialSupply = 300;
|
||||
|
||||
const minters = [minterA, minterB];
|
||||
const pausers = [pauserA, pauserB];
|
||||
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
beforeEach(async function () {
|
||||
this.token = await StandaloneERC20.new({ from: deployer });
|
||||
});
|
||||
|
||||
async function initializeFull(token, name, symbol, decimals, initialSupply, initialHolder, minters, pausers, from) {
|
||||
const callData = encodeCall('initialize', ['string', 'string', 'uint8', 'uint256', 'address', 'address[]', 'address[]'], [name, symbol, decimals, initialSupply, initialHolder, minters, pausers]);
|
||||
await token.sendTransaction({ data: callData, from });
|
||||
}
|
||||
|
||||
async function initializePartial(token, name, symbol, decimals, minters, pausers, from) {
|
||||
const callData = encodeCall('initialize', ['string', 'string', 'uint8', 'address[]', 'address[]'], [name, symbol, decimals, minters, pausers]);
|
||||
await token.sendTransaction({ data: callData, from });
|
||||
}
|
||||
|
||||
describe('with all arguments', function () {
|
||||
it('reverts if initial balance is zero', async function () {
|
||||
await assertRevert(initializeFull(this.token, name, symbol, decimals, 0, ZERO_ADDRESS, minters, pausers, deployer));
|
||||
});
|
||||
|
||||
it('can be created with no minters', async function () {
|
||||
await initializeFull(this.token, name, symbol, decimals, initialSupply, initialHolder, [], pausers, deployer);
|
||||
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('can be created with no pausers', async function () {
|
||||
await initializeFull(this.token, name, symbol, decimals, initialSupply, initialHolder, minters, [], deployer);
|
||||
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
context('with token', async function () {
|
||||
beforeEach(async function () {
|
||||
await initializeFull(this.token, name, symbol, decimals, initialSupply, initialHolder, minters, pausers, deployer);
|
||||
});
|
||||
|
||||
it('initializes metadata', async function () {
|
||||
(await this.token.name()).should.equal(name);
|
||||
(await this.token.symbol()).should.equal(symbol);
|
||||
(await this.token.decimals()).should.be.bignumber.equal(decimals);
|
||||
});
|
||||
|
||||
it('assigns the initial supply to the initial holder', async function () {
|
||||
(await this.token.balanceOf(initialHolder)).should.be.bignumber.equal(initialSupply);
|
||||
});
|
||||
|
||||
describe('mintability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all minters have the minter role', async function () {
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(true);
|
||||
}
|
||||
});
|
||||
|
||||
shouldBehaveLikeERC20Mintable(minterA, otherAccounts);
|
||||
});
|
||||
|
||||
describe('pausability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all pausers have the minter role', async function () {
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('without initial balance', function () {
|
||||
it('can be created with no minters', async function () {
|
||||
await initializePartial(this.token, name, symbol, decimals, [], pausers, deployer);
|
||||
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('can be created with no pausers', async function () {
|
||||
await initializePartial(this.token, name, symbol, decimals, minters, [], deployer);
|
||||
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
context('with token', async function () {
|
||||
beforeEach(async function () {
|
||||
await initializePartial(this.token, name, symbol, decimals, minters, pausers, deployer);
|
||||
});
|
||||
|
||||
it('initializes metadata', async function () {
|
||||
(await this.token.name()).should.equal(name);
|
||||
(await this.token.symbol()).should.equal(symbol);
|
||||
(await this.token.decimals()).should.be.bignumber.equal(decimals);
|
||||
});
|
||||
|
||||
describe('mintability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all minters have the minter role', async function () {
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(true);
|
||||
}
|
||||
});
|
||||
|
||||
shouldBehaveLikeERC20Mintable(minterA, otherAccounts);
|
||||
});
|
||||
|
||||
describe('pausability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all pausers have the minter role', async function () {
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
78
test/examples/StandaloneERC721.test.js
Normal file
78
test/examples/StandaloneERC721.test.js
Normal file
@ -0,0 +1,78 @@
|
||||
const encodeCall = require('zos-lib/lib/helpers/encodeCall').default;
|
||||
const { assertRevert } = require('../helpers/assertRevert');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
const should = require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
const StandaloneERC721 = artifacts.require('StandaloneERC721');
|
||||
|
||||
contract('StandaloneERC721', function ([_, deployer, minterA, minterB, pauserA, pauserB, anyone, ...otherAccounts]) {
|
||||
const name = "StandaloneERC721";
|
||||
const symbol = "SAERC721";
|
||||
|
||||
const minters = [minterA, minterB];
|
||||
const pausers = [pauserA, pauserB];
|
||||
|
||||
beforeEach(async function () {
|
||||
this.token = await StandaloneERC721.new({ from: deployer });
|
||||
});
|
||||
|
||||
async function initialize(token, name, symbol, minters, pausers, from) {
|
||||
const callData = encodeCall('initialize', ['string', 'string', 'address[]', 'address[]'], [name, symbol, minters, pausers]);
|
||||
await token.sendTransaction({ data: callData, from });
|
||||
}
|
||||
|
||||
it('can be created with no minters', async function () {
|
||||
await initialize(this.token, name, symbol, [], pausers, deployer);
|
||||
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('can be created with no pausers', async function () {
|
||||
await initialize(this.token, name, symbol, minters, [], deployer);
|
||||
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
context('with token', async function () {
|
||||
beforeEach(async function () {
|
||||
await initialize(this.token, name, symbol, minters, pausers, deployer);
|
||||
});
|
||||
|
||||
it('initializes metadata', async function () {
|
||||
(await this.token.name()).should.equal(name);
|
||||
(await this.token.symbol()).should.equal(symbol);
|
||||
});
|
||||
|
||||
describe('mintability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all minters have the minter role', async function () {
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('pausability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all pausers have the minter role', async function () {
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
96
test/examples/StandardToken.test.js
Normal file
96
test/examples/StandardToken.test.js
Normal file
@ -0,0 +1,96 @@
|
||||
const encodeCall = require('zos-lib/lib/helpers/encodeCall').default;
|
||||
const { shouldBehaveLikeERC20Mintable } = require('../token/ERC20/behaviors/ERC20Mintable.behavior');
|
||||
const { shouldBehaveLikePublicRole } = require('../access/roles/PublicRole.behavior');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
const should = require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
const StandardToken = artifacts.require('StandardToken');
|
||||
|
||||
contract('StandardToken', function ([_, deployer, initialHolder, minterA, minterB, pauserA, pauserB, anyone, ...otherAccounts]) {
|
||||
const name = "StdToken";
|
||||
const symbol = "STDT";
|
||||
const decimals = 18;
|
||||
|
||||
const initialSupply = 300;
|
||||
|
||||
const minters = [minterA, minterB];
|
||||
const pausers = [pauserA, pauserB];
|
||||
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
beforeEach(async function () {
|
||||
this.token = await StandardToken.new({ from: deployer });
|
||||
});
|
||||
|
||||
async function initialize(token, name, symbol, decimals, initialSupply, initialHolder, minters, pausers, from) {
|
||||
const callData = encodeCall('initialize', ['string', 'string', 'uint8', 'uint256', 'address', 'address[]', 'address[]'], [name, symbol, decimals, initialSupply, initialHolder, minters, pausers]);
|
||||
await token.sendTransaction({ data: callData, from });
|
||||
}
|
||||
|
||||
context('with all arguments', function () {
|
||||
beforeEach(async function () {
|
||||
await initialize(this.token, name, symbol, decimals, initialSupply, initialHolder, minters, pausers, deployer);
|
||||
});
|
||||
|
||||
it('initializes metadata', async function () {
|
||||
(await this.token.name()).should.equal(name);
|
||||
(await this.token.symbol()).should.equal(symbol);
|
||||
(await this.token.decimals()).should.be.bignumber.equal(decimals);
|
||||
});
|
||||
|
||||
it('assigns the initial supply to the initial holder', async function () {
|
||||
(await this.token.balanceOf(initialHolder)).should.be.bignumber.equal(initialSupply);
|
||||
});
|
||||
|
||||
describe('mintability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all minters have the minter role', async function () {
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(true);
|
||||
}
|
||||
});
|
||||
|
||||
shouldBehaveLikeERC20Mintable(minterA, otherAccounts);
|
||||
});
|
||||
|
||||
describe('pausability', function () {
|
||||
beforeEach(function () {
|
||||
this.contract = this.token;
|
||||
});
|
||||
|
||||
it('all pausers have the minter role', async function () {
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('can be created with zero initial balance', async function () {
|
||||
await initialize(this.token, name, symbol, decimals, 0, ZERO_ADDRESS, minters, pausers, deployer);
|
||||
(await this.token.balanceOf(initialHolder)).should.be.bignumber.equal(0);
|
||||
});
|
||||
|
||||
it('can be created with no minters', async function () {
|
||||
await initialize(this.token, name, symbol, decimals, initialSupply, initialHolder, [], pausers, deployer);
|
||||
|
||||
for (const minter of minters) {
|
||||
(await this.token.isMinter(minter)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('can be created with no pausers', async function () {
|
||||
await initialize(this.token, name, symbol, decimals, initialSupply, initialHolder, minters, [], deployer);
|
||||
|
||||
for (const pauser of pausers) {
|
||||
(await this.token.isPauser(pauser)).should.equal(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user