@0xcert/ethereum-erc20-contracts
Version:
Smart contract implementation of the ERC-20 standard on the Ethereum blockchain.
594 lines • 39.3 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 __1 = require("..");
const common = require("./helpers/common");
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]);
ctx.set('ttProxy', accounts[4]);
ctx.set('zeroAddress', '0x0000000000000000000000000000000000000000');
}));
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 token = ctx.get('token');
const ttProxy = ctx.get('ttProxy');
const dappToken = yield ctx.deploy({
src: './build/dapp-token-mock.json',
contract: 'DappTokenMock',
args: ['Dapp token', 'DXC', 18, token.receipt._address, ttProxy],
});
ctx.set('dappToken', dappToken);
}));
spec.beforeEach((ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const ttProxy = ctx.get('ttProxy');
const dappToken = yield ctx.deploy({
src: './build/dapp-token-mock.json',
contract: 'DappTokenMock',
args: ['Migration token', 'MXC', 18, token.receipt._address, ttProxy],
});
ctx.set('migrationToken', dappToken);
}));
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('totalTokenSupply', new BN('300000000000000000000000000'));
}));
spec.test('correctly checks all the supported interfaces', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const tokenInterface = yield dappToken.instance.methods.supportsInterface('0x36372b07').call();
const tokenNameInterface = yield dappToken.instance.methods.supportsInterface('0x06fdde03').call();
const tokenSymbolInterface = yield dappToken.instance.methods.supportsInterface('0x95d89b41').call();
const tokenDecimalsInterface = yield dappToken.instance.methods.supportsInterface('0x313ce567').call();
const tokenNoneExistingInterface = yield dappToken.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 dappToken = ctx.get('dappToken');
const actualSupply = yield dappToken.instance.methods.totalSupply().call();
ctx.is(actualSupply.toString(), '0');
}));
spec.test('has correct token name after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const actualTokenName = yield dappToken.instance.methods.name().call();
ctx.is(actualTokenName, 'Dapp token');
}));
spec.test('has correct token symbol after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const actualTokenSymbol = yield dappToken.instance.methods.symbol().call();
ctx.is(actualTokenSymbol, 'DXC');
}));
spec.test('has correct token decimals after construction', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const actualTokenDecimals = yield dappToken.instance.methods.decimals().call();
ctx.is(actualTokenDecimals, '18');
}));
spec.test('sucessfully deposits token into dapp token', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const tokenOwnerBalance = ctx.get('totalTokenSupply').sub(tokenAmount);
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
const logs = yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
ctx.not(logs.events.Transfer, undefined);
const tokenDappTokenBalance = yield token.instance.methods.balanceOf(dappToken.receipt._address).call();
const dappTokenOwnerBalance = yield dappToken.instance.methods.balanceOf(owner).call();
const actualTokenOwnerBalance = yield token.instance.methods.balanceOf(owner).call();
const actualSupply = yield dappToken.instance.methods.totalSupply().call();
const proxyAllowance = yield dappToken.instance.methods.allowance(owner, ttProxy).call();
ctx.is(dappTokenOwnerBalance.toString(), tokenAmount.toString());
ctx.is(tokenDappTokenBalance.toString(), tokenAmount.toString());
ctx.is(tokenOwnerBalance.toString(), actualTokenOwnerBalance.toString());
ctx.is(actualSupply.toString(), tokenAmount.toString());
ctx.is(proxyAllowance.toString(), tokenAmount.toString());
}));
spec.test('sucessfully deposits token into dapp token with another receiver', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const sara = ctx.get('sara');
const ttProxy = ctx.get('ttProxy');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const tokenOwnerBalance = ctx.get('totalTokenSupply').sub(tokenAmount);
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
const logs = yield dappToken.instance.methods.deposit(tokenAmount.toString(), sara).send({ from: owner });
ctx.not(logs.events.Transfer, undefined);
const tokenDappTokenBalance = yield token.instance.methods.balanceOf(dappToken.receipt._address).call();
const dappTokenOwnerBalance = yield dappToken.instance.methods.balanceOf(owner).call();
const dappTokenSaraBalance = yield dappToken.instance.methods.balanceOf(sara).call();
const actualTokenOwnerBalance = yield token.instance.methods.balanceOf(owner).call();
const actualSupply = yield dappToken.instance.methods.totalSupply().call();
const proxyAllowance = yield dappToken.instance.methods.allowance(sara, ttProxy).call();
ctx.is(dappTokenOwnerBalance.toString(), '0');
ctx.is(dappTokenSaraBalance.toString(), tokenAmount.toString());
ctx.is(tokenDappTokenBalance.toString(), tokenAmount.toString());
ctx.is(tokenOwnerBalance.toString(), actualTokenOwnerBalance.toString());
ctx.is(actualSupply.toString(), tokenAmount.toString());
ctx.is(proxyAllowance.toString(), tokenAmount.toString());
}));
spec.test('sucessfully withdraws token from dapp token', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const halfTokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('50'));
const tokenOwnerBalance = ctx.get('totalTokenSupply').sub(halfTokenAmount);
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const logs = yield dappToken.instance.methods.withdraw(halfTokenAmount.toString()).send({ from: owner });
ctx.not(logs.events.Transfer, undefined);
const tokenDappTokenBalance = yield token.instance.methods.balanceOf(dappToken.receipt._address).call();
const dappTokenOwnerBalance = yield dappToken.instance.methods.balanceOf(owner).call();
const actualTokenOwnerBalance = yield token.instance.methods.balanceOf(owner).call();
const actualSupply = yield dappToken.instance.methods.totalSupply().call();
const proxyAllowance = yield dappToken.instance.methods.allowance(owner, ttProxy).call();
ctx.is(dappTokenOwnerBalance.toString(), halfTokenAmount.toString());
ctx.is(tokenDappTokenBalance.toString(), halfTokenAmount.toString());
ctx.is(tokenOwnerBalance.toString(), actualTokenOwnerBalance.toString());
ctx.is(actualSupply.toString(), halfTokenAmount.toString());
ctx.is(proxyAllowance.toString(), tokenAmount.toString());
}));
spec.test('sucessfully whitelists an address', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
yield dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
const logs = yield dappToken.instance.methods.setWhitelistedRecipient(ttProxy, true).send({ from: owner });
ctx.not(logs.events.WhitelistedRecipient, undefined);
const isTTProxyWhitelisted = yield dappToken.instance.methods.whitelistedRecipients(ttProxy).call();
ctx.true(isTTProxyWhitelisted);
}));
spec.test('sucessfully transfers to a whitelisted address', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
const token = ctx.get('token');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield dappToken.instance.methods.setWhitelistedRecipient(ttProxy, true).send({ from: owner });
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const logs = yield dappToken.instance.methods.transfer(ttProxy, tokenAmount.toString()).send({ from: owner });
const ttProxyBalance = yield dappToken.instance.methods.balanceOf(ttProxy).call();
const ownerBalance = yield dappToken.instance.methods.balanceOf(owner).call();
ctx.not(logs.events.Transfer, undefined);
ctx.is(ttProxyBalance.toString(), tokenAmount.toString());
ctx.is(ownerBalance.toString(), '0');
}));
spec.test('sucessfully transfersFrom to a whitelisted address', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
const token = ctx.get('token');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield dappToken.instance.methods.setWhitelistedRecipient(ttProxy, true).send({ from: owner });
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield dappToken.instance.methods.approve(ttProxy, tokenAmount.toString()).send({ from: owner });
const logs = yield dappToken.instance.methods.transferFrom(owner, ttProxy, tokenAmount.toString()).send({ from: ttProxy });
const ttProxyBalance = yield dappToken.instance.methods.balanceOf(ttProxy).call();
const ownerBalance = yield dappToken.instance.methods.balanceOf(owner).call();
ctx.not(logs.events.Transfer, undefined);
ctx.is(ttProxyBalance.toString(), tokenAmount.toString());
ctx.is(ownerBalance.toString(), '0');
}));
spec.test('fails transferring to a non whitelisted address', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
const token = ctx.get('token');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield ctx.reverts(() => dappToken.instance.methods.transfer(ttProxy, tokenAmount.toString()).send({ from: owner }), '010003');
}));
spec.test('fails transfersFrom to a non whitelisted address', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const ttProxy = ctx.get('ttProxy');
const token = ctx.get('token');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield dappToken.instance.methods.approve(ttProxy, tokenAmount.toString()).send({ from: owner });
yield ctx.reverts(() => dappToken.instance.methods.transferFrom(owner, ttProxy, tokenAmount.toString()).send({ from: ttProxy }), '010003');
}));
spec.test('succesfully migrates migrateToken to dappToken', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const dappToken = ctx.get('dappToken');
const migrationToken = ctx.get('migrationToken');
const owner = ctx.get('owner');
const decimalsMul = ctx.get('decimalsMul');
const ttProxy = ctx.get('ttProxy');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const tokenOwnerBalance = ctx.get('totalTokenSupply').sub(tokenAmount);
yield token.instance.methods.approve(migrationToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield migrationToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_MIGRATE_ADDRESS).send({ from: owner });
yield migrationToken.instance.methods.startMigration(dappToken.receipt._address).send({ from: owner });
yield dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_MIGRATION_CALLER).send({ from: owner });
yield dappToken.instance.methods.setApprovedMigrator(migrationToken.receipt._address, true).send({ from: owner });
const logs = yield migrationToken.instance.methods.migrate().send({ from: owner });
ctx.not(logs.events.Transfer, undefined);
const tokenDappTokenBalance = yield token.instance.methods.balanceOf(dappToken.receipt._address).call();
const dappTokenOwnerBalance = yield dappToken.instance.methods.balanceOf(owner).call();
const migrationTokenOwnerBalance = yield migrationToken.instance.methods.balanceOf(owner).call();
const actualTokenOwnerBalance = yield token.instance.methods.balanceOf(owner).call();
const dappTokenActualSupply = yield dappToken.instance.methods.totalSupply().call();
const migrationTokenActualSupply = yield migrationToken.instance.methods.totalSupply().call();
const proxyAllowance = yield dappToken.instance.methods.allowance(owner, ttProxy).call();
ctx.is(dappTokenOwnerBalance.toString(), tokenAmount.toString());
ctx.is(tokenDappTokenBalance.toString(), tokenAmount.toString());
ctx.is(migrationTokenOwnerBalance.toString(), '0');
ctx.is(migrationTokenActualSupply.toString(), '0');
ctx.is(tokenOwnerBalance.toString(), actualTokenOwnerBalance.toString());
ctx.is(dappTokenActualSupply.toString(), tokenAmount.toString());
ctx.is(proxyAllowance.toString(), tokenAmount.toString());
}));
spec.test('fails to migrate if migration address not set', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const migrationToken = ctx.get('migrationToken');
const owner = ctx.get('owner');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(migrationToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield migrationToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield ctx.reverts(() => migrationToken.instance.methods.migrate().send({ from: owner }), '010004');
}));
spec.test('fails to migrate if migration caller is not set', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const migrationToken = ctx.get('migrationToken');
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(migrationToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield migrationToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_MIGRATE_ADDRESS).send({ from: owner });
yield migrationToken.instance.methods.startMigration(dappToken.receipt._address).send({ from: owner });
yield ctx.reverts(() => migrationToken.instance.methods.migrate().send({ from: owner }), '010006');
}));
spec.test('fails to deposit after migration started', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const migrationToken = ctx.get('migrationToken');
const dappToken = ctx.get('dappToken');
const owner = ctx.get('owner');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_MIGRATE_ADDRESS).send({ from: owner });
yield migrationToken.instance.methods.startMigration(dappToken.receipt._address).send({ from: owner });
yield token.instance.methods.approve(migrationToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield ctx.reverts(() => migrationToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner }), '010005');
}));
spec.test('fails to transfer after migration started', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const migrationToken = ctx.get('migrationToken');
const dappToken = ctx.get('dappToken');
const ttProxy = ctx.get('ttProxy');
const owner = ctx.get('owner');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(migrationToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield migrationToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield migrationToken.instance.methods.setWhitelistedRecipient(ttProxy, true).send({ from: owner });
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_MIGRATE_ADDRESS).send({ from: owner });
yield migrationToken.instance.methods.startMigration(dappToken.receipt._address).send({ from: owner });
yield ctx.reverts(() => migrationToken.instance.methods.transfer(ttProxy, tokenAmount.toString()).send({ from: owner }), '010005');
}));
spec.test('fails to transferFrom after migration started', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const token = ctx.get('token');
const migrationToken = ctx.get('migrationToken');
const dappToken = ctx.get('dappToken');
const ttProxy = ctx.get('ttProxy');
const owner = ctx.get('owner');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
yield token.instance.methods.approve(migrationToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield migrationToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield migrationToken.instance.methods.setWhitelistedRecipient(ttProxy, true).send({ from: owner });
yield migrationToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_MIGRATE_ADDRESS).send({ from: owner });
yield migrationToken.instance.methods.startMigration(dappToken.receipt._address).send({ from: owner });
yield migrationToken.instance.methods.approve(ttProxy, tokenAmount.toString()).send({ from: owner });
yield ctx.reverts(() => migrationToken.instance.methods.transferFrom(owner, ttProxy, tokenAmount.toString()).send({ from: ttProxy }), '010005');
}));
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 dappToken = ctx.get('dappToken');
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 moreThanBalance = tokenAmount.add(new ctx.web3.utils.BN('1'));
yield dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield dappToken.instance.methods.setWhitelistedRecipient(bob, true).send({ from: owner });
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield ctx.reverts(() => dappToken.instance.methods.transfer(bob, moreThanBalance.toString()).send({ from: owner }), '010001');
}));
spec.test('returns the correct allowance amount after approval', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 dappToken.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
const actualAllowance = yield dappToken.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 dappToken = ctx.get('dappToken');
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 dappToken.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 dappToken = ctx.get('dappToken');
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 dappToken.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.approve(bob, 0).send({ from: owner });
yield dappToken.instance.methods.approve(bob, newTokenAmount.toString()).send({ from: owner });
const actualAllowance = yield dappToken.instance.methods.allowance(owner, bob).call();
ctx.is(actualAllowance.toString(), newTokenAmount.toString());
}));
spec.test('correctly approves with signature', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() + 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, owner);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 0,
};
const signatureDataTuple = ctx.tuple(signatureData);
const logs = yield dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob });
const actualAllowance = yield dappToken.instance.methods.allowance(owner, sara).call();
const bobBalance = yield dappToken.instance.methods.balanceOf(bob).call();
ctx.not(logs.events.Approval, undefined);
ctx.not(logs.events.Transfer, undefined);
ctx.is(actualAllowance.toString(), tokenAmount.toString());
ctx.is(bobBalance.toString(), feeAmount.toString());
}));
spec.test('correctly approves with signature with any performer', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
const token = ctx.get('token');
const owner = ctx.get('owner');
const bob = ctx.get('bob');
const sara = ctx.get('sara');
const zeroAddress = ctx.get('zeroAddress');
const decimalsMul = ctx.get('decimalsMul');
const tokenAmount = decimalsMul.mul(new ctx.web3.utils.BN('100'));
const feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() + 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), zeroAddress, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, owner);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 0,
};
const signatureDataTuple = ctx.tuple(signatureData);
const logs = yield dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), zeroAddress, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob });
const actualAllowance = yield dappToken.instance.methods.allowance(owner, sara).call();
const bobBalance = yield dappToken.instance.methods.balanceOf(bob).call();
ctx.not(logs.events.Approval, undefined);
ctx.not(logs.events.Transfer, undefined);
ctx.is(actualAllowance.toString(), tokenAmount.toString());
ctx.is(bobBalance.toString(), feeAmount.toString());
}));
spec.test('fails approving with signature if signature is invalid', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() + 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, bob);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 0,
};
const signatureDataTuple = ctx.tuple(signatureData);
yield ctx.reverts(() => dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob }), '010007');
}));
spec.test('fails approving with signature if claim has expired', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() - 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, owner);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 0,
};
const signatureDataTuple = ctx.tuple(signatureData);
yield ctx.reverts(() => dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob }), '010009');
}));
spec.test('fails approving with signature if claim has already been performed', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() + 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, owner);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 0,
};
const signatureDataTuple = ctx.tuple(signatureData);
yield dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob });
yield ctx.reverts(() => dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob }), '010008');
}));
spec.test('fails approving with signature if claim has been canceled', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() + 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, owner);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 0,
};
const signatureDataTuple = ctx.tuple(signatureData);
yield dappToken.instance.methods.cancelApproveWithSignature(sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).send({ from: owner });
yield ctx.reverts(() => dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob }), '010011');
}));
spec.test('fails approving with signature if signature kind is invalid', (ctx) => __awaiter(void 0, void 0, void 0, function* () {
const dappToken = ctx.get('dappToken');
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 feeAmount = decimalsMul.mul(new ctx.web3.utils.BN('10'));
const seed = common.getCurrentTime();
const expiration = common.getCurrentTime() + 3600;
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
const claim = yield dappToken.instance.methods.generateClaim(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration).call();
const signature = yield ctx.web3.eth.sign(claim, owner);
const signatureData = {
r: signature.substr(0, 66),
s: `0x${signature.substr(66, 64)}`,
v: parseInt(`0x${signature.substr(130, 2)}`) + 27,
kind: 3,
};
const signatureDataTuple = ctx.tuple(signatureData);
yield ctx.reverts(() => dappToken.instance.methods.approveWithSignature(owner, sara, tokenAmount.toString(), bob, feeAmount.toString(), seed, expiration, signatureDataTuple).send({ from: bob }));
}));
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 dappToken = ctx.get('dappToken');
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 dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield dappToken.instance.methods.setWhitelistedRecipient(sara, true).send({ from: owner });
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield dappToken.instance.methods.approve(bob, tokenAmountAllowed.toString()).send({ from: owner });
yield ctx.reverts(() => dappToken.instance.methods.transferFrom(owner, sara, tokenAmount.toString()).send({ from: bob }), '010002');
}));
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 dappToken = ctx.get('dappToken');
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 dappToken.instance.methods.grantAbilities(owner, __1.DappTokenAbilities.SET_WHITELISTED).send({ from: owner });
yield dappToken.instance.methods.setWhitelistedRecipient(sara, true).send({ from: owner });
yield token.instance.methods.approve(dappToken.receipt._address, tokenAmount.toString()).send({ from: owner });
yield dappToken.instance.methods.deposit(tokenAmount.toString(), owner).send({ from: owner });
yield dappToken.instance.methods.approve(bob, tokenAmount.toString()).send({ from: owner });
yield ctx.reverts(() => dappToken.instance.methods.transferFrom(bob, sara, tokenAmountToSend.toString()).send({ from: sara }), '010001');
}));
exports.default = spec;
//# sourceMappingURL=dapp-token.test.js.map