UNPKG

@0xcert/ethereum-erc20-contracts

Version:

Smart contract implementation of the ERC-20 standard on the Ethereum blockchain.

594 lines 39.3 kB
"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