Merge branch 'solc-0.7' into solc-0.8
This commit is contained in:
@ -37,6 +37,12 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 supported', function () {
|
||||
@ -58,6 +64,12 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 and single interface supported', function () {
|
||||
@ -79,6 +91,12 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('ERC165 and many interfaces supported', function () {
|
||||
@ -117,6 +135,34 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('supports all interfaceIds via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, this.supportedInterfaces);
|
||||
expect(supported.length).to.equal(3);
|
||||
expect(supported[0]).to.equal(true);
|
||||
expect(supported[1]).to.equal(true);
|
||||
expect(supported[2]).to.equal(true);
|
||||
});
|
||||
|
||||
it('supports none of the interfaces queried via getSupportedInterfaces', async function () {
|
||||
const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2];
|
||||
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported.length).to.equal(2);
|
||||
expect(supported[0]).to.equal(false);
|
||||
expect(supported[1]).to.equal(false);
|
||||
});
|
||||
|
||||
it('supports not all of the interfaces queried via getSupportedInterfaces', async function () {
|
||||
const interfaceIdsToTest = [...this.supportedInterfaces, DUMMY_UNSUPPORTED_ID];
|
||||
|
||||
const supported = await this.mock.getSupportedInterfaces(this.target.address, interfaceIdsToTest);
|
||||
expect(supported.length).to.equal(4);
|
||||
expect(supported[0]).to.equal(true);
|
||||
expect(supported[1]).to.equal(true);
|
||||
expect(supported[2]).to.equal(true);
|
||||
expect(supported[3]).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('account address does not support ERC165', function () {
|
||||
@ -134,5 +180,11 @@ contract('ERC165Checker', function (accounts) {
|
||||
const supported = await this.mock.supportsAllInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]);
|
||||
expect(supported).to.equal(false);
|
||||
});
|
||||
|
||||
it('does not support mock interface via getSupportedInterfaces', async function () {
|
||||
const supported = await this.mock.getSupportedInterfaces(DUMMY_ACCOUNT, [DUMMY_ID]);
|
||||
expect(supported.length).to.equal(1);
|
||||
expect(supported[0]).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -5,142 +5,399 @@ const { expect } = require('chai');
|
||||
|
||||
const SafeMathMock = artifacts.require('SafeMathMock');
|
||||
|
||||
function expectStruct (value, expected) {
|
||||
for (const key in expected) {
|
||||
if (BN.isBN(value[key])) {
|
||||
expect(value[key]).to.be.bignumber.equal(expected[key]);
|
||||
} else {
|
||||
expect(value[key]).to.be.equal(expected[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contract('SafeMath', function (accounts) {
|
||||
beforeEach(async function () {
|
||||
this.safeMath = await SafeMathMock.new();
|
||||
});
|
||||
|
||||
async function testCommutative (fn, lhs, rhs, expected) {
|
||||
expect(await fn(lhs, rhs)).to.be.bignumber.equal(expected);
|
||||
expect(await fn(rhs, lhs)).to.be.bignumber.equal(expected);
|
||||
async function testCommutative (fn, lhs, rhs, expected, ...extra) {
|
||||
expect(await fn(lhs, rhs, ...extra)).to.be.bignumber.equal(expected);
|
||||
expect(await fn(rhs, lhs, ...extra)).to.be.bignumber.equal(expected);
|
||||
}
|
||||
|
||||
async function testFailsCommutative (fn, lhs, rhs) {
|
||||
await expectRevert.unspecified(fn(lhs, rhs));
|
||||
await expectRevert.unspecified(fn(rhs, lhs));
|
||||
async function testFailsCommutative (fn, lhs, rhs, reason, ...extra) {
|
||||
if (reason == undefined) {
|
||||
await expectRevert.unspecified(fn(lhs, rhs, ...extra));
|
||||
await expectRevert.unspecified(fn(rhs, lhs, ...extra));
|
||||
} else {
|
||||
await expectRevert(fn(lhs, rhs, ...extra), reason);
|
||||
await expectRevert(fn(rhs, lhs, ...extra), reason);
|
||||
}
|
||||
}
|
||||
|
||||
describe('add', function () {
|
||||
it('adds correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
async function testCommutativeIterable (fn, lhs, rhs, expected, ...extra) {
|
||||
expectStruct(await fn(lhs, rhs, ...extra), expected);
|
||||
expectStruct(await fn(rhs, lhs, ...extra), expected);
|
||||
}
|
||||
|
||||
await testCommutative(this.safeMath.add, a, b, a.add(b));
|
||||
});
|
||||
describe('with flag', function () {
|
||||
describe('add', function () {
|
||||
it('adds correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
it('reverts on addition overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('1');
|
||||
|
||||
await testFailsCommutative(this.safeMath.add, a, b);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sub', function () {
|
||||
it('subtracts correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
expect(await this.safeMath.sub(a, b)).to.be.bignumber.equal(a.sub(b));
|
||||
});
|
||||
|
||||
it('reverts if subtraction result would be negative', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
await expectRevert.unspecified(this.safeMath.sub(a, b));
|
||||
});
|
||||
});
|
||||
|
||||
describe('mul', function () {
|
||||
it('multiplies correctly', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
await testCommutative(this.safeMath.mul, a, b, a.mul(b));
|
||||
});
|
||||
|
||||
it('multiplies by zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
await testCommutative(this.safeMath.mul, a, b, '0');
|
||||
});
|
||||
|
||||
it('reverts on multiplication overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('2');
|
||||
|
||||
await testFailsCommutative(this.safeMath.mul, a, b);
|
||||
});
|
||||
});
|
||||
|
||||
describe('div', function () {
|
||||
it('divides correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.div(a, b)).to.be.bignumber.equal(a.div(b));
|
||||
});
|
||||
|
||||
it('divides zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.div(a, b)).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('returns complete number result on non-even division', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.div(a, b)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('reverts on division by zero', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
await expectRevert.unspecified(this.safeMath.div(a, b));
|
||||
});
|
||||
});
|
||||
|
||||
describe('mod', function () {
|
||||
describe('modulos correctly', async function () {
|
||||
it('when the dividend is smaller than the divisor', async function () {
|
||||
const a = new BN('284');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
testCommutativeIterable(this.safeMath.tryAdd, a, b, { flag: true, value: a.add(b) });
|
||||
});
|
||||
|
||||
it('when the dividend is equal to the divisor', async function () {
|
||||
it('reverts on addition overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('1');
|
||||
|
||||
testCommutativeIterable(this.safeMath.tryAdd, a, b, { flag: false, value: '0' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('sub', function () {
|
||||
it('subtracts correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
expectStruct(await this.safeMath.trySub(a, b), { flag: true, value: a.sub(b) });
|
||||
});
|
||||
|
||||
it('reverts if subtraction result would be negative', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
expectStruct(await this.safeMath.trySub(a, b), { flag: false, value: '0' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('mul', function () {
|
||||
it('multiplies correctly', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
testCommutativeIterable(this.safeMath.tryMul, a, b, { flag: true, value: a.mul(b) });
|
||||
});
|
||||
|
||||
it('multiplies by zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
testCommutativeIterable(this.safeMath.tryMul, a, b, { flag: true, value: a.mul(b) });
|
||||
});
|
||||
|
||||
it('reverts on multiplication overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('2');
|
||||
|
||||
testCommutativeIterable(this.safeMath.tryMul, a, b, { flag: false, value: '0' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('div', function () {
|
||||
it('divides correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
expectStruct(await this.safeMath.tryDiv(a, b), { flag: true, value: a.div(b) });
|
||||
});
|
||||
|
||||
it('when the dividend is larger than the divisor', async function () {
|
||||
it('divides zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
expectStruct(await this.safeMath.tryDiv(a, b), { flag: true, value: a.div(b) });
|
||||
});
|
||||
|
||||
it('returns complete number result on non-even division', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
expectStruct(await this.safeMath.tryDiv(a, b), { flag: true, value: a.div(b) });
|
||||
});
|
||||
|
||||
it('when the dividend is a multiple of the divisor', async function () {
|
||||
const a = new BN('17034'); // 17034 == 5678 * 3
|
||||
const b = new BN('5678');
|
||||
it('reverts on division by zero', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
expectStruct(await this.safeMath.tryDiv(a, b), { flag: false, value: '0' });
|
||||
});
|
||||
});
|
||||
|
||||
it('reverts with a 0 divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
describe('mod', function () {
|
||||
describe('modulos correctly', async function () {
|
||||
it('when the dividend is smaller than the divisor', async function () {
|
||||
const a = new BN('284');
|
||||
const b = new BN('5678');
|
||||
|
||||
await expectRevert.unspecified(this.safeMath.mod(a, b));
|
||||
expectStruct(await this.safeMath.tryMod(a, b), { flag: true, value: a.mod(b) });
|
||||
});
|
||||
|
||||
it('when the dividend is equal to the divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expectStruct(await this.safeMath.tryMod(a, b), { flag: true, value: a.mod(b) });
|
||||
});
|
||||
|
||||
it('when the dividend is larger than the divisor', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expectStruct(await this.safeMath.tryMod(a, b), { flag: true, value: a.mod(b) });
|
||||
});
|
||||
|
||||
it('when the dividend is a multiple of the divisor', async function () {
|
||||
const a = new BN('17034'); // 17034 == 5678 * 3
|
||||
const b = new BN('5678');
|
||||
|
||||
expectStruct(await this.safeMath.tryMod(a, b), { flag: true, value: a.mod(b) });
|
||||
});
|
||||
});
|
||||
|
||||
it('reverts with a 0 divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
expectStruct(await this.safeMath.tryMod(a, b), { flag: false, value: '0' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with default revert message', function () {
|
||||
describe('add', function () {
|
||||
it('adds correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
await testCommutative(this.safeMath.add, a, b, a.add(b));
|
||||
});
|
||||
|
||||
it('reverts on addition overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('1');
|
||||
|
||||
await testFailsCommutative(this.safeMath.add, a, b, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sub', function () {
|
||||
it('subtracts correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
expect(await this.safeMath.sub(a, b)).to.be.bignumber.equal(a.sub(b));
|
||||
});
|
||||
|
||||
it('reverts if subtraction result would be negative', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
await expectRevert.unspecified(this.safeMath.sub(a, b));
|
||||
});
|
||||
});
|
||||
|
||||
describe('mul', function () {
|
||||
it('multiplies correctly', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
await testCommutative(this.safeMath.mul, a, b, a.mul(b));
|
||||
});
|
||||
|
||||
it('multiplies by zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
await testCommutative(this.safeMath.mul, a, b, '0');
|
||||
});
|
||||
|
||||
it('reverts on multiplication overflow', async function () {
|
||||
const a = MAX_UINT256;
|
||||
const b = new BN('2');
|
||||
|
||||
await testFailsCommutative(this.safeMath.mul, a, b, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('div', function () {
|
||||
it('divides correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.div(a, b)).to.be.bignumber.equal(a.div(b));
|
||||
});
|
||||
|
||||
it('divides zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.div(a, b)).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('returns complete number result on non-even division', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.div(a, b)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('reverts on division by zero', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
await expectRevert.unspecified(this.safeMath.div(a, b));
|
||||
});
|
||||
});
|
||||
|
||||
describe('mod', function () {
|
||||
describe('modulos correctly', async function () {
|
||||
it('when the dividend is smaller than the divisor', async function () {
|
||||
const a = new BN('284');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
|
||||
it('when the dividend is equal to the divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
|
||||
it('when the dividend is larger than the divisor', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
|
||||
it('when the dividend is a multiple of the divisor', async function () {
|
||||
const a = new BN('17034'); // 17034 == 5678 * 3
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.mod(a, b)).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
});
|
||||
|
||||
it('reverts with a 0 divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
await expectRevert.unspecified(this.safeMath.mod(a, b));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with custom revert message', function () {
|
||||
describe('sub', function () {
|
||||
it('subtracts correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('1234');
|
||||
|
||||
expect(await this.safeMath.subWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal(a.sub(b));
|
||||
});
|
||||
|
||||
it('reverts if subtraction result would be negative', async function () {
|
||||
const a = new BN('1234');
|
||||
const b = new BN('5678');
|
||||
|
||||
await expectRevert(this.safeMath.subWithMessage(a, b, 'MyErrorMessage'), 'MyErrorMessage');
|
||||
});
|
||||
});
|
||||
|
||||
describe('div', function () {
|
||||
it('divides correctly', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.divWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal(a.div(b));
|
||||
});
|
||||
|
||||
it('divides zero correctly', async function () {
|
||||
const a = new BN('0');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.divWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('returns complete number result on non-even division', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.divWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('reverts on division by zero', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
await expectRevert(this.safeMath.divWithMessage(a, b, 'MyErrorMessage'), 'MyErrorMessage');
|
||||
});
|
||||
});
|
||||
|
||||
describe('mod', function () {
|
||||
describe('modulos correctly', async function () {
|
||||
it('when the dividend is smaller than the divisor', async function () {
|
||||
const a = new BN('284');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.modWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
|
||||
it('when the dividend is equal to the divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.modWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
|
||||
it('when the dividend is larger than the divisor', async function () {
|
||||
const a = new BN('7000');
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.modWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
|
||||
it('when the dividend is a multiple of the divisor', async function () {
|
||||
const a = new BN('17034'); // 17034 == 5678 * 3
|
||||
const b = new BN('5678');
|
||||
|
||||
expect(await this.safeMath.modWithMessage(a, b, 'MyErrorMessage')).to.be.bignumber.equal(a.mod(b));
|
||||
});
|
||||
});
|
||||
|
||||
it('reverts with a 0 divisor', async function () {
|
||||
const a = new BN('5678');
|
||||
const b = new BN('0');
|
||||
|
||||
await expectRevert(this.safeMath.modWithMessage(a, b, 'MyErrorMessage'), 'MyErrorMessage');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('memory leakage', function () {
|
||||
it('add', async function () {
|
||||
expect(await this.safeMath.addMemoryCheck()).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('sub', async function () {
|
||||
expect(await this.safeMath.subMemoryCheck()).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('mul', async function () {
|
||||
expect(await this.safeMath.mulMemoryCheck()).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('div', async function () {
|
||||
expect(await this.safeMath.divMemoryCheck()).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('mod', async function () {
|
||||
expect(await this.safeMath.modMemoryCheck()).to.be.bignumber.equal('0');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
150
test/proxy/Clones.behaviour.js
Normal file
150
test/proxy/Clones.behaviour.js
Normal file
@ -0,0 +1,150 @@
|
||||
const { expectRevert } = require('@openzeppelin/test-helpers');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
const DummyImplementation = artifacts.require('DummyImplementation');
|
||||
|
||||
module.exports = function shouldBehaveLikeClone (createClone) {
|
||||
before('deploy implementation', async function () {
|
||||
this.implementation = web3.utils.toChecksumAddress((await DummyImplementation.new()).address);
|
||||
});
|
||||
|
||||
const assertProxyInitialization = function ({ value, balance }) {
|
||||
it('initializes the proxy', async function () {
|
||||
const dummy = new DummyImplementation(this.proxy);
|
||||
expect(await dummy.value()).to.be.bignumber.equal(value.toString());
|
||||
});
|
||||
|
||||
it('has expected balance', async function () {
|
||||
expect(await web3.eth.getBalance(this.proxy)).to.be.bignumber.equal(balance.toString());
|
||||
});
|
||||
};
|
||||
|
||||
describe('initialization without parameters', function () {
|
||||
describe('non payable', function () {
|
||||
const expectedInitializedValue = 10;
|
||||
const initializeData = new DummyImplementation('').contract.methods['initializeNonPayable()']().encodeABI();
|
||||
|
||||
describe('when not sending balance', function () {
|
||||
beforeEach('creating proxy', async function () {
|
||||
this.proxy = (
|
||||
await createClone(this.implementation, initializeData)
|
||||
).address;
|
||||
});
|
||||
|
||||
assertProxyInitialization({
|
||||
value: expectedInitializedValue,
|
||||
balance: 0,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sending some balance', function () {
|
||||
const value = 10e5;
|
||||
|
||||
it('reverts', async function () {
|
||||
await expectRevert.unspecified(
|
||||
createClone(this.implementation, initializeData, { value }),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('payable', function () {
|
||||
const expectedInitializedValue = 100;
|
||||
const initializeData = new DummyImplementation('').contract.methods['initializePayable()']().encodeABI();
|
||||
|
||||
describe('when not sending balance', function () {
|
||||
beforeEach('creating proxy', async function () {
|
||||
this.proxy = (
|
||||
await createClone(this.implementation, initializeData)
|
||||
).address;
|
||||
});
|
||||
|
||||
assertProxyInitialization({
|
||||
value: expectedInitializedValue,
|
||||
balance: 0,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sending some balance', function () {
|
||||
const value = 10e5;
|
||||
|
||||
beforeEach('creating proxy', async function () {
|
||||
this.proxy = (
|
||||
await createClone(this.implementation, initializeData, { value })
|
||||
).address;
|
||||
});
|
||||
|
||||
assertProxyInitialization({
|
||||
value: expectedInitializedValue,
|
||||
balance: value,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('initialization with parameters', function () {
|
||||
describe('non payable', function () {
|
||||
const expectedInitializedValue = 10;
|
||||
const initializeData = new DummyImplementation('').contract
|
||||
.methods.initializeNonPayableWithValue(expectedInitializedValue).encodeABI();
|
||||
|
||||
describe('when not sending balance', function () {
|
||||
beforeEach('creating proxy', async function () {
|
||||
this.proxy = (
|
||||
await createClone(this.implementation, initializeData)
|
||||
).address;
|
||||
});
|
||||
|
||||
assertProxyInitialization({
|
||||
value: expectedInitializedValue,
|
||||
balance: 0,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sending some balance', function () {
|
||||
const value = 10e5;
|
||||
|
||||
it('reverts', async function () {
|
||||
await expectRevert.unspecified(
|
||||
createClone(this.implementation, initializeData, { value }),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('payable', function () {
|
||||
const expectedInitializedValue = 42;
|
||||
const initializeData = new DummyImplementation('').contract
|
||||
.methods.initializePayableWithValue(expectedInitializedValue).encodeABI();
|
||||
|
||||
describe('when not sending balance', function () {
|
||||
beforeEach('creating proxy', async function () {
|
||||
this.proxy = (
|
||||
await createClone(this.implementation, initializeData)
|
||||
).address;
|
||||
});
|
||||
|
||||
assertProxyInitialization({
|
||||
value: expectedInitializedValue,
|
||||
balance: 0,
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sending some balance', function () {
|
||||
const value = 10e5;
|
||||
|
||||
beforeEach('creating proxy', async function () {
|
||||
this.proxy = (
|
||||
await createClone(this.implementation, initializeData, { value })
|
||||
).address;
|
||||
});
|
||||
|
||||
assertProxyInitialization({
|
||||
value: expectedInitializedValue,
|
||||
balance: value,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
54
test/proxy/Clones.test.js
Normal file
54
test/proxy/Clones.test.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
|
||||
|
||||
const shouldBehaveLikeClone = require('./Clones.behaviour');
|
||||
|
||||
const ClonesMock = artifacts.require('ClonesMock');
|
||||
|
||||
contract('Clones', function (accounts) {
|
||||
describe('clone', function () {
|
||||
shouldBehaveLikeClone(async (implementation, initData, opts = {}) => {
|
||||
const factory = await ClonesMock.new();
|
||||
const receipt = await factory.clone(implementation, initData, { value: opts.value });
|
||||
const address = receipt.logs.find(({ event }) => event === 'NewInstance').args.instance;
|
||||
return { address };
|
||||
});
|
||||
});
|
||||
|
||||
describe('cloneDeterministic', function () {
|
||||
shouldBehaveLikeClone(async (implementation, initData, opts = {}) => {
|
||||
const salt = web3.utils.randomHex(32);
|
||||
const factory = await ClonesMock.new();
|
||||
const receipt = await factory.cloneDeterministic(implementation, salt, initData, { value: opts.value });
|
||||
const address = receipt.logs.find(({ event }) => event === 'NewInstance').args.instance;
|
||||
return { address };
|
||||
});
|
||||
|
||||
it('address already used', async function () {
|
||||
const implementation = web3.utils.randomHex(20);
|
||||
const salt = web3.utils.randomHex(32);
|
||||
const factory = await ClonesMock.new();
|
||||
// deploy once
|
||||
expectEvent(
|
||||
await factory.cloneDeterministic(implementation, salt, '0x'),
|
||||
'NewInstance',
|
||||
);
|
||||
// deploy twice
|
||||
await expectRevert(
|
||||
factory.cloneDeterministic(implementation, salt, '0x'),
|
||||
'ERC1167: create2 failed',
|
||||
);
|
||||
});
|
||||
|
||||
it('address prediction', async function () {
|
||||
const implementation = web3.utils.randomHex(20);
|
||||
const salt = web3.utils.randomHex(32);
|
||||
const factory = await ClonesMock.new();
|
||||
const predicted = await factory.predictDeterministicAddress(implementation, salt);
|
||||
expectEvent(
|
||||
await factory.cloneDeterministic(implementation, salt, '0x'),
|
||||
'NewInstance',
|
||||
{ instance: predicted },
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,6 +1,6 @@
|
||||
const { BN, expectRevert, expectEvent, constants } = require('@openzeppelin/test-helpers');
|
||||
const { ZERO_ADDRESS } = constants;
|
||||
const { toChecksumAddress, keccak256 } = require('ethereumjs-util');
|
||||
const ethereumjsUtil = require('ethereumjs-util');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
@ -19,6 +19,10 @@ const ClashingImplementation = artifacts.require('ClashingImplementation');
|
||||
const IMPLEMENTATION_LABEL = 'eip1967.proxy.implementation';
|
||||
const ADMIN_LABEL = 'eip1967.proxy.admin';
|
||||
|
||||
function toChecksumAddress (address) {
|
||||
return ethereumjsUtil.toChecksumAddress('0x' + address.replace(/^0x/, '').padStart(40, '0'));
|
||||
}
|
||||
|
||||
module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createProxy, accounts) {
|
||||
const [proxyAdminAddress, proxyAdminOwner, anotherAccount] = accounts;
|
||||
|
||||
@ -308,13 +312,13 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
|
||||
|
||||
describe('storage', function () {
|
||||
it('should store the implementation address in specified location', async function () {
|
||||
const slot = '0x' + new BN(keccak256(Buffer.from(IMPLEMENTATION_LABEL))).subn(1).toString(16);
|
||||
const slot = '0x' + new BN(ethereumjsUtil.keccak256(Buffer.from(IMPLEMENTATION_LABEL))).subn(1).toString(16);
|
||||
const implementation = toChecksumAddress(await web3.eth.getStorageAt(this.proxyAddress, slot));
|
||||
expect(implementation).to.be.equal(this.implementationV0);
|
||||
});
|
||||
|
||||
it('should store the admin proxy in specified location', async function () {
|
||||
const slot = '0x' + new BN(keccak256(Buffer.from(ADMIN_LABEL))).subn(1).toString(16);
|
||||
const slot = '0x' + new BN(ethereumjsUtil.keccak256(Buffer.from(ADMIN_LABEL))).subn(1).toString(16);
|
||||
const proxyAdmin = toChecksumAddress(await web3.eth.getStorageAt(this.proxyAddress, slot));
|
||||
expect(proxyAdmin).to.be.equal(proxyAdminAddress);
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const { BN, expectRevert } = require('@openzeppelin/test-helpers');
|
||||
const { toChecksumAddress, keccak256 } = require('ethereumjs-util');
|
||||
const ethereumjsUtil = require('ethereumjs-util');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
@ -7,6 +7,10 @@ const DummyImplementation = artifacts.require('DummyImplementation');
|
||||
|
||||
const IMPLEMENTATION_LABEL = 'eip1967.proxy.implementation';
|
||||
|
||||
function toChecksumAddress (address) {
|
||||
return ethereumjsUtil.toChecksumAddress('0x' + address.replace(/^0x/, '').padStart(40, '0'));
|
||||
}
|
||||
|
||||
module.exports = function shouldBehaveLikeUpgradeableProxy (createProxy, proxyAdminAddress, proxyCreator) {
|
||||
it('cannot be initialized with a non-contract address', async function () {
|
||||
const nonContractAddress = proxyCreator;
|
||||
@ -24,7 +28,7 @@ module.exports = function shouldBehaveLikeUpgradeableProxy (createProxy, proxyAd
|
||||
|
||||
const assertProxyInitialization = function ({ value, balance }) {
|
||||
it('sets the implementation address', async function () {
|
||||
const slot = '0x' + new BN(keccak256(Buffer.from(IMPLEMENTATION_LABEL))).subn(1).toString(16);
|
||||
const slot = '0x' + new BN(ethereumjsUtil.keccak256(Buffer.from(IMPLEMENTATION_LABEL))).subn(1).toString(16);
|
||||
const implementation = toChecksumAddress(await web3.eth.getStorageAt(this.proxy, slot));
|
||||
expect(implementation).to.be.equal(this.implementation);
|
||||
});
|
||||
@ -210,5 +214,17 @@ module.exports = function shouldBehaveLikeUpgradeableProxy (createProxy, proxyAd
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('reverting initialization', function () {
|
||||
const initializeData = new DummyImplementation('').contract
|
||||
.methods.reverts().encodeABI();
|
||||
|
||||
it('reverts', async function () {
|
||||
await expectRevert(
|
||||
createProxy(this.implementation, proxyAdminAddress, initializeData, { from: proxyCreator }),
|
||||
'DummyImplementation reverted',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -106,7 +106,7 @@ function shouldBehaveLikeERC1155 ([minter, firstTokenHolder, secondTokenHolder,
|
||||
[firstTokenHolder, secondTokenHolder, ZERO_ADDRESS],
|
||||
[firstTokenId, secondTokenId, unknownTokenId],
|
||||
),
|
||||
'ERC1155: batch balance query for the zero address',
|
||||
'ERC1155: balance query for the zero address',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -447,4 +447,37 @@ contract('ERC777', function (accounts) {
|
||||
expect(await this.token.defaultOperators()).to.deep.equal([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('relative order of hooks', function () {
|
||||
beforeEach(async function () {
|
||||
await singletons.ERC1820Registry(registryFunder);
|
||||
this.sender = await ERC777SenderRecipientMock.new();
|
||||
await this.sender.registerRecipient(this.sender.address);
|
||||
await this.sender.registerSender(this.sender.address);
|
||||
this.token = await ERC777.new(holder, initialSupply, name, symbol, []);
|
||||
await this.token.send(this.sender.address, 1, '0x', { from: holder });
|
||||
});
|
||||
|
||||
it('send', async function () {
|
||||
const { receipt } = await this.sender.send(this.token.address, anyone, 1, '0x');
|
||||
|
||||
const internalBeforeHook = receipt.logs.findIndex(l => l.event === 'BeforeTokenTransfer');
|
||||
expect(internalBeforeHook).to.be.gte(0);
|
||||
const externalSendHook = receipt.logs.findIndex(l => l.event === 'TokensToSendCalled');
|
||||
expect(externalSendHook).to.be.gte(0);
|
||||
|
||||
expect(externalSendHook).to.be.lt(internalBeforeHook);
|
||||
});
|
||||
|
||||
it('burn', async function () {
|
||||
const { receipt } = await this.sender.burn(this.token.address, 1, '0x');
|
||||
|
||||
const internalBeforeHook = receipt.logs.findIndex(l => l.event === 'BeforeTokenTransfer');
|
||||
expect(internalBeforeHook).to.be.gte(0);
|
||||
const externalSendHook = receipt.logs.findIndex(l => l.event === 'TokensToSendCalled');
|
||||
expect(externalSendHook).to.be.gte(0);
|
||||
|
||||
expect(externalSendHook).to.be.lt(internalBeforeHook);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
const { BN, expectEvent } = require('@openzeppelin/test-helpers');
|
||||
const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
|
||||
const { expect } = require('chai');
|
||||
|
||||
const zip = require('lodash.zip');
|
||||
@ -139,4 +139,43 @@ contract('EnumerableMap', function (accounts) {
|
||||
expect(await this.map.contains(keyB)).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('read', function () {
|
||||
beforeEach(async function () {
|
||||
await this.map.set(keyA, accountA);
|
||||
});
|
||||
|
||||
describe('get', function () {
|
||||
it('existing value', async function () {
|
||||
expect(await this.map.get(keyA)).to.be.equal(accountA);
|
||||
});
|
||||
it('missing value', async function () {
|
||||
await expectRevert(this.map.get(keyB), 'EnumerableMap: nonexistent key');
|
||||
});
|
||||
});
|
||||
|
||||
describe('get with message', function () {
|
||||
it('existing value', async function () {
|
||||
expect(await this.map.getWithMessage(keyA, 'custom error string')).to.be.equal(accountA);
|
||||
});
|
||||
it('missing value', async function () {
|
||||
await expectRevert(this.map.getWithMessage(keyB, 'custom error string'), 'custom error string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('tryGet', function () {
|
||||
it('existing value', async function () {
|
||||
expect(await this.map.tryGet(keyA)).to.be.deep.equal({
|
||||
0: true,
|
||||
1: accountA,
|
||||
});
|
||||
});
|
||||
it('missing value', async function () {
|
||||
expect(await this.map.tryGet(keyB)).to.be.deep.equal({
|
||||
0: false,
|
||||
1: constants.ZERO_ADDRESS,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user