|
@@ -1,11 +1,18 @@
|
|
|
-const { constants, expectEvent, expectRevert, time } = require('@openzeppelin/test-helpers');
|
|
|
+const { BN, constants, expectEvent, expectRevert, time } = require('@openzeppelin/test-helpers');
|
|
|
const { ZERO_BYTES32 } = constants;
|
|
|
|
|
|
const { expect } = require('chai');
|
|
|
|
|
|
+const {
|
|
|
+ shouldSupportInterfaces,
|
|
|
+} = require('../utils/introspection/SupportsInterface.behavior');
|
|
|
+
|
|
|
const TimelockController = artifacts.require('TimelockController');
|
|
|
const CallReceiverMock = artifacts.require('CallReceiverMock');
|
|
|
const Implementation2 = artifacts.require('Implementation2');
|
|
|
+const ERC721Mock = artifacts.require('ERC721Mock');
|
|
|
+const ERC1155Mock = artifacts.require('ERC1155Mock');
|
|
|
+
|
|
|
const MINDELAY = time.duration.days(1);
|
|
|
|
|
|
function genOperation (target, value, data, predecessor, salt) {
|
|
@@ -52,40 +59,44 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
beforeEach(async function () {
|
|
|
// Deploy new timelock
|
|
|
- this.timelock = await TimelockController.new(
|
|
|
+ this.mock = await TimelockController.new(
|
|
|
MINDELAY,
|
|
|
[ proposer ],
|
|
|
[ executor ],
|
|
|
{ from: admin },
|
|
|
);
|
|
|
|
|
|
- expect(await this.timelock.hasRole(CANCELLER_ROLE, proposer)).to.be.equal(true);
|
|
|
- await this.timelock.revokeRole(CANCELLER_ROLE, proposer, { from: admin });
|
|
|
- await this.timelock.grantRole(CANCELLER_ROLE, canceller, { from: admin });
|
|
|
+ expect(await this.mock.hasRole(CANCELLER_ROLE, proposer)).to.be.equal(true);
|
|
|
+ await this.mock.revokeRole(CANCELLER_ROLE, proposer, { from: admin });
|
|
|
+ await this.mock.grantRole(CANCELLER_ROLE, canceller, { from: admin });
|
|
|
|
|
|
// Mocks
|
|
|
this.callreceivermock = await CallReceiverMock.new({ from: admin });
|
|
|
this.implementation2 = await Implementation2.new({ from: admin });
|
|
|
});
|
|
|
|
|
|
+ shouldSupportInterfaces([
|
|
|
+ 'ERC1155Receiver',
|
|
|
+ ]);
|
|
|
+
|
|
|
it('initial state', async function () {
|
|
|
- expect(await this.timelock.getMinDelay()).to.be.bignumber.equal(MINDELAY);
|
|
|
+ expect(await this.mock.getMinDelay()).to.be.bignumber.equal(MINDELAY);
|
|
|
|
|
|
- expect(await this.timelock.TIMELOCK_ADMIN_ROLE()).to.be.equal(TIMELOCK_ADMIN_ROLE);
|
|
|
- expect(await this.timelock.PROPOSER_ROLE()).to.be.equal(PROPOSER_ROLE);
|
|
|
- expect(await this.timelock.EXECUTOR_ROLE()).to.be.equal(EXECUTOR_ROLE);
|
|
|
- expect(await this.timelock.CANCELLER_ROLE()).to.be.equal(CANCELLER_ROLE);
|
|
|
+ expect(await this.mock.TIMELOCK_ADMIN_ROLE()).to.be.equal(TIMELOCK_ADMIN_ROLE);
|
|
|
+ expect(await this.mock.PROPOSER_ROLE()).to.be.equal(PROPOSER_ROLE);
|
|
|
+ expect(await this.mock.EXECUTOR_ROLE()).to.be.equal(EXECUTOR_ROLE);
|
|
|
+ expect(await this.mock.CANCELLER_ROLE()).to.be.equal(CANCELLER_ROLE);
|
|
|
|
|
|
expect(await Promise.all([ PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE ].map(role =>
|
|
|
- this.timelock.hasRole(role, proposer),
|
|
|
+ this.mock.hasRole(role, proposer),
|
|
|
))).to.be.deep.equal([ true, false, false ]);
|
|
|
|
|
|
expect(await Promise.all([ PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE ].map(role =>
|
|
|
- this.timelock.hasRole(role, canceller),
|
|
|
+ this.mock.hasRole(role, canceller),
|
|
|
))).to.be.deep.equal([ false, true, false ]);
|
|
|
|
|
|
expect(await Promise.all([ PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE ].map(role =>
|
|
|
- this.timelock.hasRole(role, executor),
|
|
|
+ this.mock.hasRole(role, executor),
|
|
|
))).to.be.deep.equal([ false, false, true ]);
|
|
|
});
|
|
|
|
|
@@ -99,7 +110,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xba41db3be0a9929145cfe480bd0f1f003689104d275ae912099f925df424ef94',
|
|
|
'0x60d9109846ab510ed75c15f979ae366a8a2ace11d34ba9788c13ac296db50e6e',
|
|
|
);
|
|
|
- expect(await this.timelock.hashOperation(
|
|
|
+ expect(await this.mock.hashOperation(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -116,7 +127,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xce8f45069cc71d25f71ba05062de1a3974f9849b004de64a70998bca9d29c2e7',
|
|
|
'0x8952d74c110f72bfe5accdf828c74d53a7dfb71235dfa8a1e8c75d8576b372ff',
|
|
|
);
|
|
|
- expect(await this.timelock.hashOperationBatch(
|
|
|
+ expect(await this.mock.hashOperationBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -138,7 +149,7 @@ contract('TimelockController', function (accounts) {
|
|
|
});
|
|
|
|
|
|
it('proposer can schedule', async function () {
|
|
|
- const receipt = await this.timelock.schedule(
|
|
|
+ const receipt = await this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -159,12 +170,12 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
const block = await web3.eth.getBlock(receipt.receipt.blockHash);
|
|
|
|
|
|
- expect(await this.timelock.getTimestamp(this.operation.id))
|
|
|
+ expect(await this.mock.getTimestamp(this.operation.id))
|
|
|
.to.be.bignumber.equal(web3.utils.toBN(block.timestamp).add(MINDELAY));
|
|
|
});
|
|
|
|
|
|
it('prevent overwriting active operation', async function () {
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -175,7 +186,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
|
|
|
await expectRevert(
|
|
|
- this.timelock.schedule(
|
|
|
+ this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -190,7 +201,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('prevent non-proposer from commiting', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.schedule(
|
|
|
+ this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -205,7 +216,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('enforce minimum delay', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.schedule(
|
|
|
+ this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -232,7 +243,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('revert if operation is not scheduled', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -246,7 +257,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
describe('with scheduled operation', function () {
|
|
|
beforeEach(async function () {
|
|
|
- ({ receipt: this.receipt, logs: this.logs } = await this.timelock.schedule(
|
|
|
+ ({ receipt: this.receipt, logs: this.logs } = await this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -259,7 +270,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('revert if execution comes too early 1/2', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -272,11 +283,11 @@ contract('TimelockController', function (accounts) {
|
|
|
});
|
|
|
|
|
|
it('revert if execution comes too early 2/2', async function () {
|
|
|
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
|
|
|
+ const timestamp = await this.mock.getTimestamp(this.operation.id);
|
|
|
await time.increaseTo(timestamp - 5); // -1 is too tight, test sometime fails
|
|
|
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -290,12 +301,12 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
describe('on time', function () {
|
|
|
beforeEach(async function () {
|
|
|
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
|
|
|
+ const timestamp = await this.mock.getTimestamp(this.operation.id);
|
|
|
await time.increaseTo(timestamp);
|
|
|
});
|
|
|
|
|
|
it('executor can reveal', async function () {
|
|
|
- const receipt = await this.timelock.execute(
|
|
|
+ const receipt = await this.mock.execute(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -314,7 +325,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('prevent non-executor from revealing', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -343,7 +354,7 @@ contract('TimelockController', function (accounts) {
|
|
|
});
|
|
|
|
|
|
it('proposer can schedule', async function () {
|
|
|
- const receipt = await this.timelock.scheduleBatch(
|
|
|
+ const receipt = await this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -366,12 +377,12 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
const block = await web3.eth.getBlock(receipt.receipt.blockHash);
|
|
|
|
|
|
- expect(await this.timelock.getTimestamp(this.operation.id))
|
|
|
+ expect(await this.mock.getTimestamp(this.operation.id))
|
|
|
.to.be.bignumber.equal(web3.utils.toBN(block.timestamp).add(MINDELAY));
|
|
|
});
|
|
|
|
|
|
it('prevent overwriting active operation', async function () {
|
|
|
- await this.timelock.scheduleBatch(
|
|
|
+ await this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -382,7 +393,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
|
|
|
await expectRevert(
|
|
|
- this.timelock.scheduleBatch(
|
|
|
+ this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -397,7 +408,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('length of batch parameter must match #1', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.scheduleBatch(
|
|
|
+ this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
[],
|
|
|
this.operation.payloads,
|
|
@@ -412,7 +423,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('length of batch parameter must match #1', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.scheduleBatch(
|
|
|
+ this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
[],
|
|
@@ -427,7 +438,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('prevent non-proposer from commiting', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.scheduleBatch(
|
|
|
+ this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -442,7 +453,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('enforce minimum delay', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.scheduleBatch(
|
|
|
+ this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -469,7 +480,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('revert if operation is not scheduled', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -483,7 +494,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
describe('with scheduled operation', function () {
|
|
|
beforeEach(async function () {
|
|
|
- ({ receipt: this.receipt, logs: this.logs } = await this.timelock.scheduleBatch(
|
|
|
+ ({ receipt: this.receipt, logs: this.logs } = await this.mock.scheduleBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -496,7 +507,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('revert if execution comes too early 1/2', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -509,11 +520,11 @@ contract('TimelockController', function (accounts) {
|
|
|
});
|
|
|
|
|
|
it('revert if execution comes too early 2/2', async function () {
|
|
|
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
|
|
|
+ const timestamp = await this.mock.getTimestamp(this.operation.id);
|
|
|
await time.increaseTo(timestamp - 5); // -1 is to tight, test sometime fails
|
|
|
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -527,12 +538,12 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
describe('on time', function () {
|
|
|
beforeEach(async function () {
|
|
|
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
|
|
|
+ const timestamp = await this.mock.getTimestamp(this.operation.id);
|
|
|
await time.increaseTo(timestamp);
|
|
|
});
|
|
|
|
|
|
it('executor can reveal', async function () {
|
|
|
- const receipt = await this.timelock.executeBatch(
|
|
|
+ const receipt = await this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -553,7 +564,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('prevent non-executor from revealing', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -567,7 +578,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('length mismatch #1', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
[],
|
|
|
this.operation.values,
|
|
|
this.operation.payloads,
|
|
@@ -581,7 +592,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('length mismatch #2', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
[],
|
|
|
this.operation.payloads,
|
|
@@ -595,7 +606,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('length mismatch #3', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
this.operation.targets,
|
|
|
this.operation.values,
|
|
|
[],
|
|
@@ -630,7 +641,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0x8ac04aa0d6d66b8812fb41d39638d37af0a9ab11da507afd65c509f8ed079d3e',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.scheduleBatch(
|
|
|
+ await this.mock.scheduleBatch(
|
|
|
operation.targets,
|
|
|
operation.values,
|
|
|
operation.payloads,
|
|
@@ -641,7 +652,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
await expectRevert(
|
|
|
- this.timelock.executeBatch(
|
|
|
+ this.mock.executeBatch(
|
|
|
operation.targets,
|
|
|
operation.values,
|
|
|
operation.payloads,
|
|
@@ -664,7 +675,7 @@ contract('TimelockController', function (accounts) {
|
|
|
ZERO_BYTES32,
|
|
|
'0xa2485763600634800df9fc9646fb2c112cf98649c55f63dd1d9c7d13a64399d9',
|
|
|
);
|
|
|
- ({ receipt: this.receipt, logs: this.logs } = await this.timelock.schedule(
|
|
|
+ ({ receipt: this.receipt, logs: this.logs } = await this.mock.schedule(
|
|
|
this.operation.target,
|
|
|
this.operation.value,
|
|
|
this.operation.data,
|
|
@@ -676,20 +687,20 @@ contract('TimelockController', function (accounts) {
|
|
|
});
|
|
|
|
|
|
it('canceller can cancel', async function () {
|
|
|
- const receipt = await this.timelock.cancel(this.operation.id, { from: canceller });
|
|
|
+ const receipt = await this.mock.cancel(this.operation.id, { from: canceller });
|
|
|
expectEvent(receipt, 'Cancelled', { id: this.operation.id });
|
|
|
});
|
|
|
|
|
|
it('cannot cancel invalid operation', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.cancel(constants.ZERO_BYTES32, { from: canceller }),
|
|
|
+ this.mock.cancel(constants.ZERO_BYTES32, { from: canceller }),
|
|
|
'TimelockController: operation cannot be cancelled',
|
|
|
);
|
|
|
});
|
|
|
|
|
|
it('prevent non-canceller from canceling', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.cancel(this.operation.id, { from: other }),
|
|
|
+ this.mock.cancel(this.operation.id, { from: other }),
|
|
|
`AccessControl: account ${other.toLowerCase()} is missing role ${CANCELLER_ROLE}`,
|
|
|
);
|
|
|
});
|
|
@@ -699,7 +710,7 @@ contract('TimelockController', function (accounts) {
|
|
|
describe('maintenance', function () {
|
|
|
it('prevent unauthorized maintenance', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.updateDelay(0, { from: other }),
|
|
|
+ this.mock.updateDelay(0, { from: other }),
|
|
|
'TimelockController: caller must be timelock',
|
|
|
);
|
|
|
});
|
|
@@ -707,14 +718,14 @@ contract('TimelockController', function (accounts) {
|
|
|
it('timelock scheduled maintenance', async function () {
|
|
|
const newDelay = time.duration.hours(6);
|
|
|
const operation = genOperation(
|
|
|
- this.timelock.address,
|
|
|
+ this.mock.address,
|
|
|
0,
|
|
|
- this.timelock.contract.methods.updateDelay(newDelay.toString()).encodeABI(),
|
|
|
+ this.mock.contract.methods.updateDelay(newDelay.toString()).encodeABI(),
|
|
|
ZERO_BYTES32,
|
|
|
'0xf8e775b2c5f4d66fb5c7fa800f35ef518c262b6014b3c0aee6ea21bff157f108',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -724,7 +735,7 @@ contract('TimelockController', function (accounts) {
|
|
|
{ from: proposer },
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
- const receipt = await this.timelock.execute(
|
|
|
+ const receipt = await this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -734,7 +745,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
expectEvent(receipt, 'MinDelayChange', { newDuration: newDelay.toString(), oldDuration: MINDELAY });
|
|
|
|
|
|
- expect(await this.timelock.getMinDelay()).to.be.bignumber.equal(newDelay);
|
|
|
+ expect(await this.mock.getMinDelay()).to.be.bignumber.equal(newDelay);
|
|
|
});
|
|
|
});
|
|
|
|
|
@@ -754,7 +765,7 @@ contract('TimelockController', function (accounts) {
|
|
|
this.operation1.id,
|
|
|
'0x036e1311cac523f9548e6461e29fb1f8f9196b91910a41711ea22f5de48df07d',
|
|
|
);
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
this.operation1.target,
|
|
|
this.operation1.value,
|
|
|
this.operation1.data,
|
|
@@ -763,7 +774,7 @@ contract('TimelockController', function (accounts) {
|
|
|
MINDELAY,
|
|
|
{ from: proposer },
|
|
|
);
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
this.operation2.target,
|
|
|
this.operation2.value,
|
|
|
this.operation2.data,
|
|
@@ -777,7 +788,7 @@ contract('TimelockController', function (accounts) {
|
|
|
|
|
|
it('cannot execute before dependency', async function () {
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
this.operation2.target,
|
|
|
this.operation2.value,
|
|
|
this.operation2.data,
|
|
@@ -790,7 +801,7 @@ contract('TimelockController', function (accounts) {
|
|
|
});
|
|
|
|
|
|
it('can execute after dependency', async function () {
|
|
|
- await this.timelock.execute(
|
|
|
+ await this.mock.execute(
|
|
|
this.operation1.target,
|
|
|
this.operation1.value,
|
|
|
this.operation1.data,
|
|
@@ -798,7 +809,7 @@ contract('TimelockController', function (accounts) {
|
|
|
this.operation1.salt,
|
|
|
{ from: executor },
|
|
|
);
|
|
|
- await this.timelock.execute(
|
|
|
+ await this.mock.execute(
|
|
|
this.operation2.target,
|
|
|
this.operation2.value,
|
|
|
this.operation2.data,
|
|
@@ -821,7 +832,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0x8043596363daefc89977b25f9d9b4d06c3910959ef0c4d213557a903e1b555e2',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -831,7 +842,7 @@ contract('TimelockController', function (accounts) {
|
|
|
{ from: proposer },
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
- await this.timelock.execute(
|
|
|
+ await this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -852,7 +863,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xb1b1b276fdf1a28d1e00537ea73b04d56639128b08063c1a2f70a52e38cba693',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -863,7 +874,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -884,7 +895,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xe5ca79f295fc8327ee8a765fe19afb58f4a0cbc5053642bfdd7e73bc68e0fc67',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -895,7 +906,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -916,7 +927,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xf3274ce7c394c5b629d5215723563a744b817e1730cca5587c567099a14578fd',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -927,7 +938,7 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -948,7 +959,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0x5ab73cd33477dcd36c1e05e28362719d0ed59a7b9ff14939de63a43073dc1f44',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -959,10 +970,10 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
|
|
|
- expect(await web3.eth.getBalance(this.timelock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
+ expect(await web3.eth.getBalance(this.mock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
expect(await web3.eth.getBalance(this.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
|
|
|
- await this.timelock.execute(
|
|
|
+ await this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -971,7 +982,7 @@ contract('TimelockController', function (accounts) {
|
|
|
{ from: executor, value: 1 },
|
|
|
);
|
|
|
|
|
|
- expect(await web3.eth.getBalance(this.timelock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
+ expect(await web3.eth.getBalance(this.mock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
expect(await web3.eth.getBalance(this.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(1));
|
|
|
});
|
|
|
|
|
@@ -984,7 +995,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xb78edbd920c7867f187e5aa6294ae5a656cfbf0dea1ccdca3751b740d0f2bdf8',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -995,11 +1006,11 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
|
|
|
- expect(await web3.eth.getBalance(this.timelock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
+ expect(await web3.eth.getBalance(this.mock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
expect(await web3.eth.getBalance(this.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -1010,7 +1021,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'TimelockController: underlying transaction reverted',
|
|
|
);
|
|
|
|
|
|
- expect(await web3.eth.getBalance(this.timelock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
+ expect(await web3.eth.getBalance(this.mock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
expect(await web3.eth.getBalance(this.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
});
|
|
|
|
|
@@ -1023,7 +1034,7 @@ contract('TimelockController', function (accounts) {
|
|
|
'0xdedb4563ef0095db01d81d3f2decf57cf83e4a72aa792af14c43a792b56f4de6',
|
|
|
);
|
|
|
|
|
|
- await this.timelock.schedule(
|
|
|
+ await this.mock.schedule(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -1034,11 +1045,11 @@ contract('TimelockController', function (accounts) {
|
|
|
);
|
|
|
await time.increase(MINDELAY);
|
|
|
|
|
|
- expect(await web3.eth.getBalance(this.timelock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
+ expect(await web3.eth.getBalance(this.mock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
expect(await web3.eth.getBalance(this.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
|
|
|
await expectRevert(
|
|
|
- this.timelock.execute(
|
|
|
+ this.mock.execute(
|
|
|
operation.target,
|
|
|
operation.value,
|
|
|
operation.data,
|
|
@@ -1049,8 +1060,60 @@ contract('TimelockController', function (accounts) {
|
|
|
'TimelockController: underlying transaction reverted',
|
|
|
);
|
|
|
|
|
|
- expect(await web3.eth.getBalance(this.timelock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
+ expect(await web3.eth.getBalance(this.mock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
expect(await web3.eth.getBalance(this.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
|
|
|
});
|
|
|
});
|
|
|
+
|
|
|
+ describe('safe receive', function () {
|
|
|
+ describe('ERC721', function () {
|
|
|
+ const name = 'Non Fungible Token';
|
|
|
+ const symbol = 'NFT';
|
|
|
+ const tokenId = new BN(1);
|
|
|
+
|
|
|
+ beforeEach(async function () {
|
|
|
+ this.token = await ERC721Mock.new(name, symbol);
|
|
|
+ await this.token.mint(other, tokenId);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('can receive an ERC721 safeTransfer', async function () {
|
|
|
+ await this.token.safeTransferFrom(other, this.mock.address, tokenId, { from: other });
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('ERC1155', function () {
|
|
|
+ const uri = 'https://token-cdn-domain/{id}.json';
|
|
|
+ const tokenIds = {
|
|
|
+ 1: new BN(1000),
|
|
|
+ 2: new BN(2000),
|
|
|
+ 3: new BN(3000),
|
|
|
+ };
|
|
|
+
|
|
|
+ beforeEach(async function () {
|
|
|
+ this.token = await ERC1155Mock.new(uri);
|
|
|
+ await this.token.mintBatch(other, Object.keys(tokenIds), Object.values(tokenIds), '0x');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('can receive ERC1155 safeTransfer', async function () {
|
|
|
+ await this.token.safeTransferFrom(
|
|
|
+ other,
|
|
|
+ this.mock.address,
|
|
|
+ ...Object.entries(tokenIds)[0], // id + amount
|
|
|
+ '0x',
|
|
|
+ { from: other },
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it('can receive ERC1155 safeBatchTransfer', async function () {
|
|
|
+ await this.token.safeBatchTransferFrom(
|
|
|
+ other,
|
|
|
+ this.mock.address,
|
|
|
+ Object.keys(tokenIds),
|
|
|
+ Object.values(tokenIds),
|
|
|
+ '0x',
|
|
|
+ { from: other },
|
|
|
+ );
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
});
|