557 lines
19 KiB
JavaScript
557 lines
19 KiB
JavaScript
|
const { contract, web3 } = require('@openzeppelin/test-environment');
|
||
|
const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
|
||
|
const { ZERO_ADDRESS } = constants;
|
||
|
|
||
|
const { expect } = require('chai');
|
||
|
|
||
|
const ERC777SenderRecipientMock = contract.fromArtifact('ERC777SenderRecipientMock');
|
||
|
|
||
|
function shouldBehaveLikeERC777DirectSendBurn (holder, recipient, data) {
|
||
|
shouldBehaveLikeERC777DirectSend(holder, recipient, data);
|
||
|
shouldBehaveLikeERC777DirectBurn(holder, data);
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777OperatorSendBurn (holder, recipient, operator, data, operatorData) {
|
||
|
shouldBehaveLikeERC777OperatorSend(holder, recipient, operator, data, operatorData);
|
||
|
shouldBehaveLikeERC777OperatorBurn(holder, operator, data, operatorData);
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777UnauthorizedOperatorSendBurn (holder, recipient, operator, data, operatorData) {
|
||
|
shouldBehaveLikeERC777UnauthorizedOperatorSend(holder, recipient, operator, data, operatorData);
|
||
|
shouldBehaveLikeERC777UnauthorizedOperatorBurn(holder, operator, data, operatorData);
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777DirectSend (holder, recipient, data) {
|
||
|
describe('direct send', function () {
|
||
|
context('when the sender has tokens', function () {
|
||
|
shouldDirectSendTokens(holder, recipient, new BN('0'), data);
|
||
|
shouldDirectSendTokens(holder, recipient, new BN('1'), data);
|
||
|
|
||
|
it('reverts when sending more than the balance', async function () {
|
||
|
const balance = await this.token.balanceOf(holder);
|
||
|
await expectRevert.unspecified(this.token.send(recipient, balance.addn(1), data, { from: holder }));
|
||
|
});
|
||
|
|
||
|
it('reverts when sending to the zero address', async function () {
|
||
|
await expectRevert.unspecified(this.token.send(ZERO_ADDRESS, new BN('1'), data, { from: holder }));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
context('when the sender has no tokens', function () {
|
||
|
removeBalance(holder);
|
||
|
|
||
|
shouldDirectSendTokens(holder, recipient, new BN('0'), data);
|
||
|
|
||
|
it('reverts when sending a non-zero amount', async function () {
|
||
|
await expectRevert.unspecified(this.token.send(recipient, new BN('1'), data, { from: holder }));
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777OperatorSend (holder, recipient, operator, data, operatorData) {
|
||
|
describe('operator send', function () {
|
||
|
context('when the sender has tokens', async function () {
|
||
|
shouldOperatorSendTokens(holder, operator, recipient, new BN('0'), data, operatorData);
|
||
|
shouldOperatorSendTokens(holder, operator, recipient, new BN('1'), data, operatorData);
|
||
|
|
||
|
it('reverts when sending more than the balance', async function () {
|
||
|
const balance = await this.token.balanceOf(holder);
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorSend(holder, recipient, balance.addn(1), data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('reverts when sending to the zero address', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorSend(
|
||
|
holder, ZERO_ADDRESS, new BN('1'), data, operatorData, { from: operator }
|
||
|
)
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
context('when the sender has no tokens', function () {
|
||
|
removeBalance(holder);
|
||
|
|
||
|
shouldOperatorSendTokens(holder, operator, recipient, new BN('0'), data, operatorData);
|
||
|
|
||
|
it('reverts when sending a non-zero amount', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorSend(holder, recipient, new BN('1'), data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('reverts when sending from the zero address', async function () {
|
||
|
// This is not yet reflected in the spec
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorSend(
|
||
|
ZERO_ADDRESS, recipient, new BN('0'), data, operatorData, { from: operator }
|
||
|
)
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777UnauthorizedOperatorSend (holder, recipient, operator, data, operatorData) {
|
||
|
describe('operator send', function () {
|
||
|
it('reverts', async function () {
|
||
|
await expectRevert.unspecified(this.token.operatorSend(holder, recipient, new BN('0'), data, operatorData));
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777DirectBurn (holder, data) {
|
||
|
describe('direct burn', function () {
|
||
|
context('when the sender has tokens', function () {
|
||
|
shouldDirectBurnTokens(holder, new BN('0'), data);
|
||
|
shouldDirectBurnTokens(holder, new BN('1'), data);
|
||
|
|
||
|
it('reverts when burning more than the balance', async function () {
|
||
|
const balance = await this.token.balanceOf(holder);
|
||
|
await expectRevert.unspecified(this.token.burn(balance.addn(1), data, { from: holder }));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
context('when the sender has no tokens', function () {
|
||
|
removeBalance(holder);
|
||
|
|
||
|
shouldDirectBurnTokens(holder, new BN('0'), data);
|
||
|
|
||
|
it('reverts when burning a non-zero amount', async function () {
|
||
|
await expectRevert.unspecified(this.token.burn(new BN('1'), data, { from: holder }));
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777OperatorBurn (holder, operator, data, operatorData) {
|
||
|
describe('operator burn', function () {
|
||
|
context('when the sender has tokens', async function () {
|
||
|
shouldOperatorBurnTokens(holder, operator, new BN('0'), data, operatorData);
|
||
|
shouldOperatorBurnTokens(holder, operator, new BN('1'), data, operatorData);
|
||
|
|
||
|
it('reverts when burning more than the balance', async function () {
|
||
|
const balance = await this.token.balanceOf(holder);
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorBurn(holder, balance.addn(1), data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
context('when the sender has no tokens', function () {
|
||
|
removeBalance(holder);
|
||
|
|
||
|
shouldOperatorBurnTokens(holder, operator, new BN('0'), data, operatorData);
|
||
|
|
||
|
it('reverts when burning a non-zero amount', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorBurn(holder, new BN('1'), data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('reverts when burning from the zero address', async function () {
|
||
|
// This is not yet reflected in the spec
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorBurn(
|
||
|
ZERO_ADDRESS, new BN('0'), data, operatorData, { from: operator }
|
||
|
)
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777UnauthorizedOperatorBurn (holder, operator, data, operatorData) {
|
||
|
describe('operator burn', function () {
|
||
|
it('reverts', async function () {
|
||
|
await expectRevert.unspecified(this.token.operatorBurn(holder, new BN('0'), data, operatorData));
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldDirectSendTokens (from, to, amount, data) {
|
||
|
shouldSendTokens(from, null, to, amount, data, null);
|
||
|
}
|
||
|
|
||
|
function shouldOperatorSendTokens (from, operator, to, amount, data, operatorData) {
|
||
|
shouldSendTokens(from, operator, to, amount, data, operatorData);
|
||
|
}
|
||
|
|
||
|
function shouldSendTokens (from, operator, to, amount, data, operatorData) {
|
||
|
const operatorCall = operator !== null;
|
||
|
|
||
|
it(`${operatorCall ? 'operator ' : ''}can send an amount of ${amount}`, async function () {
|
||
|
const initialTotalSupply = await this.token.totalSupply();
|
||
|
const initialFromBalance = await this.token.balanceOf(from);
|
||
|
const initialToBalance = await this.token.balanceOf(to);
|
||
|
|
||
|
let logs;
|
||
|
if (!operatorCall) {
|
||
|
({ logs } = await this.token.send(to, amount, data, { from }));
|
||
|
expectEvent.inLogs(logs, 'Sent', {
|
||
|
operator: from,
|
||
|
from,
|
||
|
to,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData: null,
|
||
|
});
|
||
|
} else {
|
||
|
({ logs } = await this.token.operatorSend(from, to, amount, data, operatorData, { from: operator }));
|
||
|
expectEvent.inLogs(logs, 'Sent', {
|
||
|
operator,
|
||
|
from,
|
||
|
to,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
expectEvent.inLogs(logs, 'Transfer', {
|
||
|
from,
|
||
|
to,
|
||
|
value: amount,
|
||
|
});
|
||
|
|
||
|
const finalTotalSupply = await this.token.totalSupply();
|
||
|
const finalFromBalance = await this.token.balanceOf(from);
|
||
|
const finalToBalance = await this.token.balanceOf(to);
|
||
|
|
||
|
expect(finalTotalSupply).to.be.bignumber.equal(initialTotalSupply);
|
||
|
expect(finalToBalance.sub(initialToBalance)).to.be.bignumber.equal(amount);
|
||
|
expect(finalFromBalance.sub(initialFromBalance)).to.be.bignumber.equal(amount.neg());
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldDirectBurnTokens (from, amount, data) {
|
||
|
shouldBurnTokens(from, null, amount, data, null);
|
||
|
}
|
||
|
|
||
|
function shouldOperatorBurnTokens (from, operator, amount, data, operatorData) {
|
||
|
shouldBurnTokens(from, operator, amount, data, operatorData);
|
||
|
}
|
||
|
|
||
|
function shouldBurnTokens (from, operator, amount, data, operatorData) {
|
||
|
const operatorCall = operator !== null;
|
||
|
|
||
|
it(`${operatorCall ? 'operator ' : ''}can burn an amount of ${amount}`, async function () {
|
||
|
const initialTotalSupply = await this.token.totalSupply();
|
||
|
const initialFromBalance = await this.token.balanceOf(from);
|
||
|
|
||
|
let logs;
|
||
|
if (!operatorCall) {
|
||
|
({ logs } = await this.token.burn(amount, data, { from }));
|
||
|
expectEvent.inLogs(logs, 'Burned', {
|
||
|
operator: from,
|
||
|
from,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData: null,
|
||
|
});
|
||
|
} else {
|
||
|
({ logs } = await this.token.operatorBurn(from, amount, data, operatorData, { from: operator }));
|
||
|
expectEvent.inLogs(logs, 'Burned', {
|
||
|
operator,
|
||
|
from,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
expectEvent.inLogs(logs, 'Transfer', {
|
||
|
from,
|
||
|
to: ZERO_ADDRESS,
|
||
|
value: amount,
|
||
|
});
|
||
|
|
||
|
const finalTotalSupply = await this.token.totalSupply();
|
||
|
const finalFromBalance = await this.token.balanceOf(from);
|
||
|
|
||
|
expect(finalTotalSupply.sub(initialTotalSupply)).to.be.bignumber.equal(amount.neg());
|
||
|
expect(finalFromBalance.sub(initialFromBalance)).to.be.bignumber.equal(amount.neg());
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777InternalMint (recipient, operator, amount, data, operatorData) {
|
||
|
shouldInternalMintTokens(operator, recipient, new BN('0'), data, operatorData);
|
||
|
shouldInternalMintTokens(operator, recipient, amount, data, operatorData);
|
||
|
|
||
|
it('reverts when minting tokens for the zero address', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.mintInternal(ZERO_ADDRESS, amount, data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldInternalMintTokens (operator, to, amount, data, operatorData) {
|
||
|
it(`can (internal) mint an amount of ${amount}`, async function () {
|
||
|
const initialTotalSupply = await this.token.totalSupply();
|
||
|
const initialToBalance = await this.token.balanceOf(to);
|
||
|
|
||
|
const { logs } = await this.token.mintInternal(to, amount, data, operatorData, { from: operator });
|
||
|
|
||
|
expectEvent.inLogs(logs, 'Minted', {
|
||
|
operator,
|
||
|
to,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData,
|
||
|
});
|
||
|
|
||
|
expectEvent.inLogs(logs, 'Transfer', {
|
||
|
from: ZERO_ADDRESS,
|
||
|
to,
|
||
|
value: amount,
|
||
|
});
|
||
|
|
||
|
const finalTotalSupply = await this.token.totalSupply();
|
||
|
const finalToBalance = await this.token.balanceOf(to);
|
||
|
|
||
|
expect(finalTotalSupply.sub(initialTotalSupply)).to.be.bignumber.equal(amount);
|
||
|
expect(finalToBalance.sub(initialToBalance)).to.be.bignumber.equal(amount);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777SendBurnMintInternalWithReceiveHook (operator, amount, data, operatorData) {
|
||
|
context('when TokensRecipient reverts', function () {
|
||
|
beforeEach(async function () {
|
||
|
await this.tokensRecipientImplementer.setShouldRevertReceive(true);
|
||
|
});
|
||
|
|
||
|
it('send reverts', async function () {
|
||
|
await expectRevert.unspecified(sendFromHolder(this.token, this.sender, this.recipient, amount, data));
|
||
|
});
|
||
|
|
||
|
it('operatorSend reverts', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorSend(this.sender, this.recipient, amount, data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('mint (internal) reverts', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.mintInternal(this.recipient, amount, data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
context('when TokensRecipient does not revert', function () {
|
||
|
beforeEach(async function () {
|
||
|
await this.tokensRecipientImplementer.setShouldRevertSend(false);
|
||
|
});
|
||
|
|
||
|
it('TokensRecipient receives send data and is called after state mutation', async function () {
|
||
|
const { tx } = await sendFromHolder(this.token, this.sender, this.recipient, amount, data);
|
||
|
|
||
|
const postSenderBalance = await this.token.balanceOf(this.sender);
|
||
|
const postRecipientBalance = await this.token.balanceOf(this.recipient);
|
||
|
|
||
|
await assertTokensReceivedCalled(
|
||
|
this.token,
|
||
|
tx,
|
||
|
this.sender,
|
||
|
this.sender,
|
||
|
this.recipient,
|
||
|
amount,
|
||
|
data,
|
||
|
null,
|
||
|
postSenderBalance,
|
||
|
postRecipientBalance,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('TokensRecipient receives operatorSend data and is called after state mutation', async function () {
|
||
|
const { tx } = await this.token.operatorSend(
|
||
|
this.sender, this.recipient, amount, data, operatorData,
|
||
|
{ from: operator },
|
||
|
);
|
||
|
|
||
|
const postSenderBalance = await this.token.balanceOf(this.sender);
|
||
|
const postRecipientBalance = await this.token.balanceOf(this.recipient);
|
||
|
|
||
|
await assertTokensReceivedCalled(
|
||
|
this.token,
|
||
|
tx,
|
||
|
operator,
|
||
|
this.sender,
|
||
|
this.recipient,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData,
|
||
|
postSenderBalance,
|
||
|
postRecipientBalance,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('TokensRecipient receives mint (internal) data and is called after state mutation', async function () {
|
||
|
const { tx } = await this.token.mintInternal(
|
||
|
this.recipient, amount, data, operatorData, { from: operator }
|
||
|
);
|
||
|
|
||
|
const postRecipientBalance = await this.token.balanceOf(this.recipient);
|
||
|
|
||
|
await assertTokensReceivedCalled(
|
||
|
this.token,
|
||
|
tx,
|
||
|
operator,
|
||
|
ZERO_ADDRESS,
|
||
|
this.recipient,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData,
|
||
|
new BN('0'),
|
||
|
postRecipientBalance,
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function shouldBehaveLikeERC777SendBurnWithSendHook (operator, amount, data, operatorData) {
|
||
|
context('when TokensSender reverts', function () {
|
||
|
beforeEach(async function () {
|
||
|
await this.tokensSenderImplementer.setShouldRevertSend(true);
|
||
|
});
|
||
|
|
||
|
it('send reverts', async function () {
|
||
|
await expectRevert.unspecified(sendFromHolder(this.token, this.sender, this.recipient, amount, data));
|
||
|
});
|
||
|
|
||
|
it('operatorSend reverts', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorSend(this.sender, this.recipient, amount, data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('burn reverts', async function () {
|
||
|
await expectRevert.unspecified(burnFromHolder(this.token, this.sender, amount, data));
|
||
|
});
|
||
|
|
||
|
it('operatorBurn reverts', async function () {
|
||
|
await expectRevert.unspecified(
|
||
|
this.token.operatorBurn(this.sender, amount, data, operatorData, { from: operator })
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
context('when TokensSender does not revert', function () {
|
||
|
beforeEach(async function () {
|
||
|
await this.tokensSenderImplementer.setShouldRevertSend(false);
|
||
|
});
|
||
|
|
||
|
it('TokensSender receives send data and is called before state mutation', async function () {
|
||
|
const preSenderBalance = await this.token.balanceOf(this.sender);
|
||
|
const preRecipientBalance = await this.token.balanceOf(this.recipient);
|
||
|
|
||
|
const { tx } = await sendFromHolder(this.token, this.sender, this.recipient, amount, data);
|
||
|
|
||
|
await assertTokensToSendCalled(
|
||
|
this.token,
|
||
|
tx,
|
||
|
this.sender,
|
||
|
this.sender,
|
||
|
this.recipient,
|
||
|
amount,
|
||
|
data,
|
||
|
null,
|
||
|
preSenderBalance,
|
||
|
preRecipientBalance,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('TokensSender receives operatorSend data and is called before state mutation', async function () {
|
||
|
const preSenderBalance = await this.token.balanceOf(this.sender);
|
||
|
const preRecipientBalance = await this.token.balanceOf(this.recipient);
|
||
|
|
||
|
const { tx } = await this.token.operatorSend(
|
||
|
this.sender, this.recipient, amount, data, operatorData,
|
||
|
{ from: operator },
|
||
|
);
|
||
|
|
||
|
await assertTokensToSendCalled(
|
||
|
this.token,
|
||
|
tx,
|
||
|
operator,
|
||
|
this.sender,
|
||
|
this.recipient,
|
||
|
amount,
|
||
|
data,
|
||
|
operatorData,
|
||
|
preSenderBalance,
|
||
|
preRecipientBalance,
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('TokensSender receives burn data and is called before state mutation', async function () {
|
||
|
const preSenderBalance = await this.token.balanceOf(this.sender);
|
||
|
|
||
|
const { tx } = await burnFromHolder(this.token, this.sender, amount, data, { from: this.sender });
|
||
|
|
||
|
await assertTokensToSendCalled(
|
||
|
this.token, tx, this.sender, this.sender, ZERO_ADDRESS, amount, data, null, preSenderBalance
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('TokensSender receives operatorBurn data and is called before state mutation', async function () {
|
||
|
const preSenderBalance = await this.token.balanceOf(this.sender);
|
||
|
|
||
|
const { tx } = await this.token.operatorBurn(this.sender, amount, data, operatorData, { from: operator });
|
||
|
|
||
|
await assertTokensToSendCalled(
|
||
|
this.token, tx, operator, this.sender, ZERO_ADDRESS, amount, data, operatorData, preSenderBalance
|
||
|
);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function removeBalance (holder) {
|
||
|
beforeEach(async function () {
|
||
|
await this.token.burn(await this.token.balanceOf(holder), '0x', { from: holder });
|
||
|
expect(await this.token.balanceOf(holder)).to.be.bignumber.equal('0');
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function assertTokensReceivedCalled (token, txHash, operator, from, to, amount, data, operatorData, fromBalance,
|
||
|
toBalance = '0') {
|
||
|
await expectEvent.inTransaction(txHash, ERC777SenderRecipientMock, 'TokensReceivedCalled', {
|
||
|
operator, from, to, amount, data, operatorData, token: token.address, fromBalance, toBalance,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function assertTokensToSendCalled (token, txHash, operator, from, to, amount, data, operatorData, fromBalance,
|
||
|
toBalance = '0') {
|
||
|
await expectEvent.inTransaction(txHash, ERC777SenderRecipientMock, 'TokensToSendCalled', {
|
||
|
operator, from, to, amount, data, operatorData, token: token.address, fromBalance, toBalance,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function sendFromHolder (token, holder, to, amount, data) {
|
||
|
if ((await web3.eth.getCode(holder)).length <= '0x'.length) {
|
||
|
return token.send(to, amount, data, { from: holder });
|
||
|
} else {
|
||
|
// assume holder is ERC777SenderRecipientMock contract
|
||
|
return (await ERC777SenderRecipientMock.at(holder)).send(token.address, to, amount, data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function burnFromHolder (token, holder, amount, data) {
|
||
|
if ((await web3.eth.getCode(holder)).length <= '0x'.length) {
|
||
|
return token.burn(amount, data, { from: holder });
|
||
|
} else {
|
||
|
// assume holder is ERC777SenderRecipientMock contract
|
||
|
return (await ERC777SenderRecipientMock.at(holder)).burn(token.address, amount, data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
shouldBehaveLikeERC777DirectSendBurn,
|
||
|
shouldBehaveLikeERC777OperatorSendBurn,
|
||
|
shouldBehaveLikeERC777UnauthorizedOperatorSendBurn,
|
||
|
shouldBehaveLikeERC777InternalMint,
|
||
|
shouldBehaveLikeERC777SendBurnMintInternalWithReceiveHook,
|
||
|
shouldBehaveLikeERC777SendBurnWithSendHook,
|
||
|
};
|