Implement recommendations from 5.0 audit Phase 1A (#4398)
Co-authored-by: Francisco Giordano <fg@frang.io> Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
This commit is contained in:
@ -46,145 +46,145 @@ contract('ERC20', function (accounts) {
|
||||
describe('when the spender is not the zero address', function () {
|
||||
const spender = recipient;
|
||||
|
||||
function shouldDecreaseApproval(amount) {
|
||||
describe('when there was no approved amount before', function () {
|
||||
function shouldDecreaseApproval(value) {
|
||||
describe('when there was no approved value before', function () {
|
||||
it('reverts', async function () {
|
||||
const allowance = await this.token.allowance(initialHolder, spender);
|
||||
await expectRevertCustomError(
|
||||
this.token.decreaseAllowance(spender, amount, { from: initialHolder }),
|
||||
this.token.decreaseAllowance(spender, value, { from: initialHolder }),
|
||||
'ERC20FailedDecreaseAllowance',
|
||||
[spender, allowance, amount],
|
||||
[spender, allowance, value],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
const approvedAmount = amount;
|
||||
describe('when the spender had an approved value', function () {
|
||||
const approvedValue = value;
|
||||
|
||||
beforeEach(async function () {
|
||||
await this.token.approve(spender, approvedAmount, { from: initialHolder });
|
||||
await this.token.approve(spender, approvedValue, { from: initialHolder });
|
||||
});
|
||||
|
||||
it('emits an approval event', async function () {
|
||||
expectEvent(
|
||||
await this.token.decreaseAllowance(spender, approvedAmount, { from: initialHolder }),
|
||||
await this.token.decreaseAllowance(spender, approvedValue, { from: initialHolder }),
|
||||
'Approval',
|
||||
{ owner: initialHolder, spender: spender, value: new BN(0) },
|
||||
);
|
||||
});
|
||||
|
||||
it('decreases the spender allowance subtracting the requested amount', async function () {
|
||||
await this.token.decreaseAllowance(spender, approvedAmount.subn(1), { from: initialHolder });
|
||||
it('decreases the spender allowance subtracting the requested value', async function () {
|
||||
await this.token.decreaseAllowance(spender, approvedValue.subn(1), { from: initialHolder });
|
||||
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('sets the allowance to zero when all allowance is removed', async function () {
|
||||
await this.token.decreaseAllowance(spender, approvedAmount, { from: initialHolder });
|
||||
await this.token.decreaseAllowance(spender, approvedValue, { from: initialHolder });
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('reverts when more than the full allowance is removed', async function () {
|
||||
await expectRevertCustomError(
|
||||
this.token.decreaseAllowance(spender, approvedAmount.addn(1), { from: initialHolder }),
|
||||
this.token.decreaseAllowance(spender, approvedValue.addn(1), { from: initialHolder }),
|
||||
'ERC20FailedDecreaseAllowance',
|
||||
[spender, approvedAmount, approvedAmount.addn(1)],
|
||||
[spender, approvedValue, approvedValue.addn(1)],
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('when the sender has enough balance', function () {
|
||||
const amount = initialSupply;
|
||||
const value = initialSupply;
|
||||
|
||||
shouldDecreaseApproval(amount);
|
||||
shouldDecreaseApproval(value);
|
||||
});
|
||||
|
||||
describe('when the sender does not have enough balance', function () {
|
||||
const amount = initialSupply.addn(1);
|
||||
const value = initialSupply.addn(1);
|
||||
|
||||
shouldDecreaseApproval(amount);
|
||||
shouldDecreaseApproval(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender is the zero address', function () {
|
||||
const amount = initialSupply;
|
||||
const value = initialSupply;
|
||||
const spender = ZERO_ADDRESS;
|
||||
|
||||
it('reverts', async function () {
|
||||
await expectRevertCustomError(
|
||||
this.token.decreaseAllowance(spender, amount, { from: initialHolder }),
|
||||
this.token.decreaseAllowance(spender, value, { from: initialHolder }),
|
||||
'ERC20FailedDecreaseAllowance',
|
||||
[spender, 0, amount],
|
||||
[spender, 0, value],
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('increase allowance', function () {
|
||||
const amount = initialSupply;
|
||||
const value = initialSupply;
|
||||
|
||||
describe('when the spender is not the zero address', function () {
|
||||
const spender = recipient;
|
||||
|
||||
describe('when the sender has enough balance', function () {
|
||||
it('emits an approval event', async function () {
|
||||
expectEvent(await this.token.increaseAllowance(spender, amount, { from: initialHolder }), 'Approval', {
|
||||
expectEvent(await this.token.increaseAllowance(spender, value, { from: initialHolder }), 'Approval', {
|
||||
owner: initialHolder,
|
||||
spender: spender,
|
||||
value: amount,
|
||||
value: value,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there was no approved amount before', function () {
|
||||
it('approves the requested amount', async function () {
|
||||
await this.token.increaseAllowance(spender, amount, { from: initialHolder });
|
||||
describe('when there was no approved value before', function () {
|
||||
it('approves the requested value', async function () {
|
||||
await this.token.increaseAllowance(spender, value, { from: initialHolder });
|
||||
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount);
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
describe('when the spender had an approved value', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.approve(spender, new BN(1), { from: initialHolder });
|
||||
});
|
||||
|
||||
it('increases the spender allowance adding the requested amount', async function () {
|
||||
await this.token.increaseAllowance(spender, amount, { from: initialHolder });
|
||||
it('increases the spender allowance adding the requested value', async function () {
|
||||
await this.token.increaseAllowance(spender, value, { from: initialHolder });
|
||||
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount.addn(1));
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value.addn(1));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the sender does not have enough balance', function () {
|
||||
const amount = initialSupply.addn(1);
|
||||
const value = initialSupply.addn(1);
|
||||
|
||||
it('emits an approval event', async function () {
|
||||
expectEvent(await this.token.increaseAllowance(spender, amount, { from: initialHolder }), 'Approval', {
|
||||
expectEvent(await this.token.increaseAllowance(spender, value, { from: initialHolder }), 'Approval', {
|
||||
owner: initialHolder,
|
||||
spender: spender,
|
||||
value: amount,
|
||||
value: value,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there was no approved amount before', function () {
|
||||
it('approves the requested amount', async function () {
|
||||
await this.token.increaseAllowance(spender, amount, { from: initialHolder });
|
||||
describe('when there was no approved value before', function () {
|
||||
it('approves the requested value', async function () {
|
||||
await this.token.increaseAllowance(spender, value, { from: initialHolder });
|
||||
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount);
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the spender had an approved amount', function () {
|
||||
describe('when the spender had an approved value', function () {
|
||||
beforeEach(async function () {
|
||||
await this.token.approve(spender, new BN(1), { from: initialHolder });
|
||||
});
|
||||
|
||||
it('increases the spender allowance adding the requested amount', async function () {
|
||||
await this.token.increaseAllowance(spender, amount, { from: initialHolder });
|
||||
it('increases the spender allowance adding the requested value', async function () {
|
||||
await this.token.increaseAllowance(spender, value, { from: initialHolder });
|
||||
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(amount.addn(1));
|
||||
expect(await this.token.allowance(initialHolder, spender)).to.be.bignumber.equal(value.addn(1));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -195,7 +195,7 @@ contract('ERC20', function (accounts) {
|
||||
|
||||
it('reverts', async function () {
|
||||
await expectRevertCustomError(
|
||||
this.token.increaseAllowance(spender, amount, { from: initialHolder }),
|
||||
this.token.increaseAllowance(spender, value, { from: initialHolder }),
|
||||
'ERC20InvalidSpender',
|
||||
[ZERO_ADDRESS],
|
||||
);
|
||||
@ -204,11 +204,9 @@ contract('ERC20', function (accounts) {
|
||||
});
|
||||
|
||||
describe('_mint', function () {
|
||||
const amount = new BN(50);
|
||||
const value = new BN(50);
|
||||
it('rejects a null account', async function () {
|
||||
await expectRevertCustomError(this.token.$_mint(ZERO_ADDRESS, amount), 'ERC20InvalidReceiver', [
|
||||
ZERO_ADDRESS,
|
||||
]);
|
||||
await expectRevertCustomError(this.token.$_mint(ZERO_ADDRESS, value), 'ERC20InvalidReceiver', [ZERO_ADDRESS]);
|
||||
});
|
||||
|
||||
it('rejects overflow', async function () {
|
||||
@ -221,22 +219,22 @@ contract('ERC20', function (accounts) {
|
||||
|
||||
describe('for a non zero account', function () {
|
||||
beforeEach('minting', async function () {
|
||||
this.receipt = await this.token.$_mint(recipient, amount);
|
||||
this.receipt = await this.token.$_mint(recipient, value);
|
||||
});
|
||||
|
||||
it('increments totalSupply', async function () {
|
||||
const expectedSupply = initialSupply.add(amount);
|
||||
const expectedSupply = initialSupply.add(value);
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(expectedSupply);
|
||||
});
|
||||
|
||||
it('increments recipient balance', async function () {
|
||||
expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(amount);
|
||||
expect(await this.token.balanceOf(recipient)).to.be.bignumber.equal(value);
|
||||
});
|
||||
|
||||
it('emits Transfer event', async function () {
|
||||
const event = expectEvent(this.receipt, 'Transfer', { from: ZERO_ADDRESS, to: recipient });
|
||||
|
||||
expect(event.args.value).to.be.bignumber.equal(amount);
|
||||
expect(event.args.value).to.be.bignumber.equal(value);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -257,81 +255,81 @@ contract('ERC20', function (accounts) {
|
||||
);
|
||||
});
|
||||
|
||||
const describeBurn = function (description, amount) {
|
||||
const describeBurn = function (description, value) {
|
||||
describe(description, function () {
|
||||
beforeEach('burning', async function () {
|
||||
this.receipt = await this.token.$_burn(initialHolder, amount);
|
||||
this.receipt = await this.token.$_burn(initialHolder, value);
|
||||
});
|
||||
|
||||
it('decrements totalSupply', async function () {
|
||||
const expectedSupply = initialSupply.sub(amount);
|
||||
const expectedSupply = initialSupply.sub(value);
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(expectedSupply);
|
||||
});
|
||||
|
||||
it('decrements initialHolder balance', async function () {
|
||||
const expectedBalance = initialSupply.sub(amount);
|
||||
const expectedBalance = initialSupply.sub(value);
|
||||
expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(expectedBalance);
|
||||
});
|
||||
|
||||
it('emits Transfer event', async function () {
|
||||
const event = expectEvent(this.receipt, 'Transfer', { from: initialHolder, to: ZERO_ADDRESS });
|
||||
|
||||
expect(event.args.value).to.be.bignumber.equal(amount);
|
||||
expect(event.args.value).to.be.bignumber.equal(value);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
describeBurn('for entire balance', initialSupply);
|
||||
describeBurn('for less amount than balance', initialSupply.subn(1));
|
||||
describeBurn('for less value than balance', initialSupply.subn(1));
|
||||
});
|
||||
});
|
||||
|
||||
describe('_update', function () {
|
||||
const amount = new BN(1);
|
||||
const value = new BN(1);
|
||||
|
||||
it('from is the zero address', async function () {
|
||||
const balanceBefore = await this.token.balanceOf(initialHolder);
|
||||
const totalSupply = await this.token.totalSupply();
|
||||
|
||||
expectEvent(await this.token.$_update(ZERO_ADDRESS, initialHolder, amount), 'Transfer', {
|
||||
expectEvent(await this.token.$_update(ZERO_ADDRESS, initialHolder, value), 'Transfer', {
|
||||
from: ZERO_ADDRESS,
|
||||
to: initialHolder,
|
||||
value: amount,
|
||||
value: value,
|
||||
});
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.add(amount));
|
||||
expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.add(amount));
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.add(value));
|
||||
expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.add(value));
|
||||
});
|
||||
|
||||
it('to is the zero address', async function () {
|
||||
const balanceBefore = await this.token.balanceOf(initialHolder);
|
||||
const totalSupply = await this.token.totalSupply();
|
||||
|
||||
expectEvent(await this.token.$_update(initialHolder, ZERO_ADDRESS, amount), 'Transfer', {
|
||||
expectEvent(await this.token.$_update(initialHolder, ZERO_ADDRESS, value), 'Transfer', {
|
||||
from: initialHolder,
|
||||
to: ZERO_ADDRESS,
|
||||
value: amount,
|
||||
value: value,
|
||||
});
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.sub(amount));
|
||||
expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.sub(amount));
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply.sub(value));
|
||||
expect(await this.token.balanceOf(initialHolder)).to.be.bignumber.equal(balanceBefore.sub(value));
|
||||
});
|
||||
|
||||
it('from and to are the zero address', async function () {
|
||||
const totalSupply = await this.token.totalSupply();
|
||||
|
||||
await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, amount);
|
||||
await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, value);
|
||||
|
||||
expect(await this.token.totalSupply()).to.be.bignumber.equal(totalSupply);
|
||||
expectEvent(await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, amount), 'Transfer', {
|
||||
expectEvent(await this.token.$_update(ZERO_ADDRESS, ZERO_ADDRESS, value), 'Transfer', {
|
||||
from: ZERO_ADDRESS,
|
||||
to: ZERO_ADDRESS,
|
||||
value: amount,
|
||||
value: value,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('_transfer', function () {
|
||||
shouldBehaveLikeERC20Transfer(initialHolder, recipient, initialSupply, function (from, to, amount) {
|
||||
return this.token.$_transfer(from, to, amount);
|
||||
shouldBehaveLikeERC20Transfer(initialHolder, recipient, initialSupply, function (from, to, value) {
|
||||
return this.token.$_transfer(from, to, value);
|
||||
});
|
||||
|
||||
describe('when the sender is the zero address', function () {
|
||||
@ -346,8 +344,8 @@ contract('ERC20', function (accounts) {
|
||||
});
|
||||
|
||||
describe('_approve', function () {
|
||||
shouldBehaveLikeERC20Approve(initialHolder, recipient, initialSupply, function (owner, spender, amount) {
|
||||
return this.token.$_approve(owner, spender, amount);
|
||||
shouldBehaveLikeERC20Approve(initialHolder, recipient, initialSupply, function (owner, spender, value) {
|
||||
return this.token.$_approve(owner, spender, value);
|
||||
});
|
||||
|
||||
describe('when the owner is the zero address', function () {
|
||||
|
||||
Reference in New Issue
Block a user