-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
297 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
pragma solidity ^0.4.21; | ||
|
||
import "./MintableToken.sol"; | ||
import "../../ownership/rbac/RBACWithAdmin.sol"; | ||
|
||
|
||
/** | ||
* @title RBACMintableToken | ||
* @author Vittorio Minacori (@vittominacori) | ||
* @dev Simple ERC20 Mintable Token, with RBAC minter permissions | ||
*/ | ||
contract RBACMintableToken is MintableToken, RBACWithAdmin { | ||
/** | ||
* A constant role name for indicating minters. | ||
*/ | ||
string public constant ROLE_MINTER = "minter"; | ||
|
||
modifier hasMintPermission() { | ||
checkRole(msg.sender, ROLE_MINTER); | ||
_; | ||
} | ||
|
||
modifier hasFinishMintingPermission() { | ||
checkRole(msg.sender, ROLE_ADMIN); | ||
_; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import ether from '../helpers/ether'; | ||
|
||
const BigNumber = web3.BigNumber; | ||
|
||
const should = require('chai') | ||
.use(require('chai-as-promised')) | ||
.use(require('chai-bignumber')(BigNumber)) | ||
.should(); | ||
|
||
const MintedCrowdsale = artifacts.require('MintedCrowdsaleImpl'); | ||
const RBACMintableToken = artifacts.require('RBACMintableToken'); | ||
|
||
const ROLE_MINTER = 'minter'; | ||
|
||
contract('MintedCrowdsale using RBACMintableToken', function ([_, investor, wallet, purchaser]) { | ||
const rate = new BigNumber(1000); | ||
const value = ether(5); | ||
|
||
const expectedTokenAmount = rate.mul(value); | ||
|
||
beforeEach(async function () { | ||
this.token = await RBACMintableToken.new(); | ||
this.crowdsale = await MintedCrowdsale.new(rate, wallet, this.token.address); | ||
await this.token.adminAddRole(this.crowdsale.address, ROLE_MINTER); | ||
}); | ||
|
||
describe('accepting payments', function () { | ||
it('should have minter role on token', async function () { | ||
const isMinter = await this.token.hasRole(this.crowdsale.address, ROLE_MINTER); | ||
isMinter.should.equal(true); | ||
}); | ||
|
||
it('should accept payments', async function () { | ||
await this.crowdsale.send(value).should.be.fulfilled; | ||
await this.crowdsale.buyTokens(investor, { value: value, from: purchaser }).should.be.fulfilled; | ||
}); | ||
}); | ||
|
||
describe('high-level purchase', function () { | ||
it('should log purchase', async function () { | ||
const { logs } = await this.crowdsale.sendTransaction({ value: value, from: investor }); | ||
const event = logs.find(e => e.event === 'TokenPurchase'); | ||
should.exist(event); | ||
event.args.purchaser.should.equal(investor); | ||
event.args.beneficiary.should.equal(investor); | ||
event.args.value.should.be.bignumber.equal(value); | ||
event.args.amount.should.be.bignumber.equal(expectedTokenAmount); | ||
}); | ||
|
||
it('should assign tokens to sender', async function () { | ||
await this.crowdsale.sendTransaction({ value: value, from: investor }); | ||
let balance = await this.token.balanceOf(investor); | ||
balance.should.be.bignumber.equal(expectedTokenAmount); | ||
}); | ||
|
||
it('should forward funds to wallet', async function () { | ||
const pre = web3.eth.getBalance(wallet); | ||
await this.crowdsale.sendTransaction({ value, from: investor }); | ||
const post = web3.eth.getBalance(wallet); | ||
post.minus(pre).should.be.bignumber.equal(value); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import assertRevert from '../../helpers/assertRevert'; | ||
|
||
const BigNumber = web3.BigNumber; | ||
|
||
require('chai') | ||
.use(require('chai-as-promised')) | ||
.use(require('chai-bignumber')(BigNumber)) | ||
.should(); | ||
|
||
export default function ([owner, anotherAccount]) { | ||
describe('as a basic mintable token', function () { | ||
describe('minting finished', function () { | ||
describe('when the token minting is not finished', function () { | ||
it('returns false', async function () { | ||
const mintingFinished = await this.token.mintingFinished(); | ||
assert.equal(mintingFinished, false); | ||
}); | ||
}); | ||
|
||
describe('when the token is minting finished', function () { | ||
beforeEach(async function () { | ||
await this.token.finishMinting({ from: owner }); | ||
}); | ||
|
||
it('returns true', async function () { | ||
const mintingFinished = await this.token.mintingFinished(); | ||
assert.equal(mintingFinished, true); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('finish minting', function () { | ||
describe('when the sender has the finishMinting permission', function () { | ||
const from = owner; | ||
|
||
describe('when the token minting was not finished', function () { | ||
it('finishes token minting', async function () { | ||
await this.token.finishMinting({ from }); | ||
|
||
const mintingFinished = await this.token.mintingFinished(); | ||
assert.equal(mintingFinished, true); | ||
}); | ||
|
||
it('emits a mint finished event', async function () { | ||
const { logs } = await this.token.finishMinting({ from }); | ||
|
||
assert.equal(logs.length, 1); | ||
assert.equal(logs[0].event, 'MintFinished'); | ||
}); | ||
}); | ||
|
||
describe('when the token minting was already finished', function () { | ||
beforeEach(async function () { | ||
await this.token.finishMinting({ from }); | ||
}); | ||
|
||
it('reverts', async function () { | ||
await assertRevert(this.token.finishMinting({ from })); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('when the sender has not the finishMinting permission', function () { | ||
const from = anotherAccount; | ||
|
||
describe('when the token minting was not finished', function () { | ||
it('reverts', async function () { | ||
await assertRevert(this.token.finishMinting({ from })); | ||
}); | ||
}); | ||
|
||
describe('when the token was already finished', function () { | ||
beforeEach(async function () { | ||
await this.token.finishMinting({ from: owner }); | ||
}); | ||
|
||
it('reverts', async function () { | ||
await assertRevert(this.token.finishMinting({ from })); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.