@0xcert/ethereum-erc20-contracts
Version:
Smart contract implementation of the ERC-20 standard on the Ethereum blockchain.
189 lines • 11 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const spec_1 = require("@specron/spec");
const spec = new spec_1.Spec();
spec.beforeEach((ctx) => __awaiter(void 0, void 0, void 0, function* () {
const accounts = yield ctx.web3.eth.getAccounts();
ctx.set('owner', accounts[0]);
ctx.set('bob', accounts[1]);
ctx.set('jane', accounts[2]);
ctx.set('sara', accounts[3]);
}));
spec.beforeEach((ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = yield ctx.deploy({
src: './build/token-mock.json',
contract: 'TokenMock',
args: ['ERC20', 'ERC', 18, '300000000000000000000000000'],
});
ctx.set('token', token);
}));
spec.beforeEach((ctx) => __awaiter(void 0, void 0, void 0, function* () {
const BN = ctx.web3.utils.BN;
ctx.set('decimalsMul', new BN('1000000000000000000'));
ctx.set('totalSupply', new BN('300000000000000000000000000'));
}));
spec.test('correctly checks all the supported interfaces', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const tokenInterface = yield token.instance.methods.supportsInterface('0x36372b07').call();
const tokenNameInterface = yield token.instance.methods.supportsInterface('0x06fdde03').call();
const tokenSymbolInterface = yield token.instance.methods.supportsInterface('0x95d89b41').call();
const tokenDecimalsInterface = yield token.instance.methods.supportsInterface('0x313ce567').call();
const tokenNoneExistingInterface = yield token.instance.methods.supportsInterface('0x19be5360').call();
ctx.is(tokenInterface, true);
ctx.is(tokenNameInterface, true);
ctx.is(tokenSymbolInterface, true);
ctx.is(tokenDecimalsInterface, true);
ctx.is(tokenNoneExistingInterface, false);
}));
spec.test('has correct totalSupply after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const actualSupply = yield token.instance.methods.totalSupply().call();
const tokenTotalSupply = ctx.get('totalSupply');
ctx.is(actualSupply.toString(), tokenTotalSupply.toString());
}));
spec.test('has correct token name after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const actualTokenName = yield token.instance.methods.name().call();
ctx.is(actualTokenName, 'ERC20');
}));
spec.test('has correct token symbol after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const actualTokenSymbol = yield token.instance.methods.symbol().call();
ctx.is(actualTokenSymbol, 'ERC');
}));
spec.test('has correct token decimals after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const actualTokenDecimals = yield token.instance.methods.decimals().call();
ctx.is(actualTokenDecimals, '18');
}));
spec.test('has correct owner token balance after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const actualOwnerBalance = yield token.instance.methods.balanceOf(owner).call();
const ownerBalance = ctx.get('totalSupply');
ctx.is(actualOwnerBalance.toString(), ownerBalance.toString());
}));
spec.test('recipient and sender have correct balances after transfer', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const ownerBalance = ctx.get('totalSupply');
yield token.instance.methods.transfer(bob, tokenAmount.toString()).send({ from: owner });
const actualOwnerBalance = yield token.instance.methods.balanceOf(owner).call();
const actualBobBalance = yield token.instance.methods.balanceOf(bob).call();
ctx.is(actualOwnerBalance.toString(), ownerBalance.sub(tokenAmount).toString());
ctx.is(actualBobBalance.toString(), tokenAmount.toString());
}));
spec.test('emits Transfer event on transfer', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const logs = yield token.instance.methods.transfer(bob, tokenAmount.toString()).send({ from: owner });
ctx.not(logs.events.Transfer, undefined);
}));
spec.test('throws when trying to transfer more than available balance', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const tokenTotalSupply = ctx.get('totalSupply');
const moreThanBalance = tokenTotalSupply.add(new ctx.web3.utils.BN('1'));
yield ctx.reverts(() => token.instance.methods.transfer(bob, moreThanBalance.toString()).send({ from: owner }), '001001');
}));
spec.test('returns the correct allowance amount after approval', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
const actualAllowance = yield token.instance.methods.allowance(owner, bob).call();
ctx.is(actualAllowance.toString(), tokenAmount.toString());
}));
spec.test('emits Approval event after approval', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const logs = yield token.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
ctx.not(logs.events.Approval, undefined);
}));
spec.test('successfully resets allowance', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const newTokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('50'));
yield token.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
yield token.instance.methods.approve(bob, 0).send({ from: owner });
yield token.instance.methods.approve(bob, newTokenAmount.toString()).send({ from: owner });
const actualAllowance = yield token.instance.methods.allowance(owner, bob).call();
ctx.is(actualAllowance.toString(), newTokenAmount.toString());
}));
spec.test('returns correct balances after transferring from another account', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const sara = ctx.get('sara');
const decimalsMul = ctx.get('decimalsMul');
const ownerSupply = ctx.get('totalSupply');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
yield token.instance.methods.transferFrom(owner, sara, tokenAmount.toString()).send({ from: bob });
const balanceOwner = yield token.instance.methods.balanceOf(owner).call();
const balanceSara = yield token.instance.methods.balanceOf(sara).call();
const balanceBob = yield token.instance.methods.balanceOf(bob).call();
ctx.is(balanceOwner.toString(), ownerSupply.sub(tokenAmount).toString());
ctx.is(balanceSara.toString(), tokenAmount.toString());
ctx.is(balanceBob.toString(), '0');
}));
spec.test('emits Transfer event on transferFrom', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const sara = ctx.get('sara');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
const logs = yield token.instance.methods.transferFrom(owner, sara, tokenAmount.toString()).send({ from: bob });
ctx.not(logs.events.Transfer, undefined);
}));
spec.test('throws when trying to transferFrom more than allowed amount', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const sara = ctx.get('sara');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const tokenAmountAllowed = decimalsMul.mul(new ctx.web3.utils.BN('99'));
yield token.instance.methods.approve(bob, tokenAmountAllowed.toString()).send({ from: owner });
yield ctx.reverts(() => token.instance.methods.transferFrom(owner, sara, tokenAmount.toString()).send({ from: bob }), '001002');
}));
spec.test('throws an error when trying to transferFrom more than _from has', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const sara = ctx.get('sara');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const tokenAmountToSend = decimalsMul.mul(new ctx.web3.utils.BN('101'));
yield token.instance.methods.transfer(bob, tokenAmount.toString()).send({ from: owner });
yield token.instance.methods.approve(sara, tokenAmount.toString()).send({ from: bob });
yield ctx.reverts(() => token.instance.methods.transferFrom(bob, sara, tokenAmountToSend.toString()).send({ from: sara }), '001001');
}));
exports.default = spec;
//# sourceMappingURL=token.test.js.map