123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997 |
- const { accounts, contract, web3, config } = require('@openzeppelin/test-environment');
- const { constants, expectEvent, expectRevert, time } = require('@openzeppelin/test-helpers');
- const { ZERO_BYTES32 } = constants;
- const { expect } = require('chai');
- const TimelockController = contract.fromArtifact('TimelockController');
- const CallReceiverMock = contract.fromArtifact('CallReceiverMock');
- const Implementation2 = contract.fromArtifact('Implementation2');
- const MINDELAY = time.duration.days(1);
- function genOperation (target, value, data, predecessor, salt) {
- const id = web3.utils.keccak256(web3.eth.abi.encodeParameters([
- 'address',
- 'uint256',
- 'bytes',
- 'uint256',
- 'bytes32',
- ], [
- target,
- value,
- data,
- predecessor,
- salt,
- ]));
- return { id, target, value, data, predecessor, salt };
- }
- function genOperationBatch (targets, values, datas, predecessor, salt) {
- const id = web3.utils.keccak256(web3.eth.abi.encodeParameters([
- 'address[]',
- 'uint256[]',
- 'bytes[]',
- 'uint256',
- 'bytes32',
- ], [
- targets,
- values,
- datas,
- predecessor,
- salt,
- ]));
- return { id, targets, values, datas, predecessor, salt };
- }
- describe('TimelockController', function () {
- const [ admin, proposer, executor, other ] = accounts;
- beforeEach(async function () {
- // Deploy new timelock
- this.timelock = await TimelockController.new(
- MINDELAY,
- [ proposer ],
- [ executor ],
- { from: admin },
- );
- // Mocks
- this.callreceivermock = await CallReceiverMock.new({ from: admin });
- this.implementation2 = await Implementation2.new({ from: admin });
- });
- it('initial state', async function () {
- expect(await this.timelock.getMinDelay()).to.be.bignumber.equal(MINDELAY);
- });
- describe('methods', function () {
- describe('operation hashing', function () {
- it('hashOperation', async function () {
- this.operation = genOperation(
- '0x29cebefe301c6ce1bb36b58654fea275e1cacc83',
- '0xf94fdd6e21da21d2',
- '0xa3bc5104',
- '0xba41db3be0a9929145cfe480bd0f1f003689104d275ae912099f925df424ef94',
- '0x60d9109846ab510ed75c15f979ae366a8a2ace11d34ba9788c13ac296db50e6e',
- );
- expect(await this.timelock.hashOperation(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- )).to.be.equal(this.operation.id);
- });
- it('hashOperationBatch', async function () {
- this.operation = genOperationBatch(
- Array(8).fill('0x2d5f21620e56531c1d59c2df9b8e95d129571f71'),
- Array(8).fill('0x2b993cfce932ccee'),
- Array(8).fill('0xcf51966b'),
- '0xce8f45069cc71d25f71ba05062de1a3974f9849b004de64a70998bca9d29c2e7',
- '0x8952d74c110f72bfe5accdf828c74d53a7dfb71235dfa8a1e8c75d8576b372ff',
- );
- expect(await this.timelock.hashOperationBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- )).to.be.equal(this.operation.id);
- });
- });
- describe('simple', function () {
- describe('schedule', function () {
- beforeEach(async function () {
- this.operation = genOperation(
- '0x31754f590B97fD975Eb86938f18Cc304E264D2F2',
- 0,
- '0x3bf92ccc',
- ZERO_BYTES32,
- '0x025e7b0be353a74631ad648c667493c0e1cd31caa4cc2d3520fdc171ea0cc726',
- );
- });
- it('proposer can schedule', async function () {
- const receipt = await this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- );
- expectEvent(receipt, 'CallScheduled', {
- id: this.operation.id,
- index: web3.utils.toBN(0),
- target: this.operation.target,
- value: web3.utils.toBN(this.operation.value),
- data: this.operation.data,
- predecessor: this.operation.predecessor,
- delay: MINDELAY,
- });
- const block = await web3.eth.getBlock(receipt.receipt.blockHash);
- expect(await this.timelock.getTimestamp(this.operation.id))
- .to.be.bignumber.equal(web3.utils.toBN(block.timestamp).add(MINDELAY));
- });
- it('prevent overwritting active operation', async function () {
- await this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await expectRevert(
- this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- ),
- 'TimelockController: operation already scheduled',
- );
- });
- it('prevent non-proposer from commiting', async function () {
- await expectRevert(
- this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: other },
- ),
- 'TimelockController: sender requires permission',
- );
- });
- it('enforce minimum delay', async function () {
- await expectRevert(
- this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY - 1,
- { from: proposer },
- ),
- 'TimelockController: insufficient delay',
- );
- });
- });
- describe('execute', function () {
- beforeEach(async function () {
- this.operation = genOperation(
- '0xAe22104DCD970750610E6FE15E623468A98b15f7',
- 0,
- '0x13e414de',
- ZERO_BYTES32,
- '0xc1059ed2dc130227aa1d1d539ac94c641306905c020436c636e19e3fab56fc7f',
- );
- });
- it('revert if operation is not scheduled', async function () {
- await expectRevert(
- this.timelock.execute(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: operation is not ready',
- );
- });
- describe('with scheduled operation', function () {
- beforeEach(async function () {
- ({ receipt: this.receipt, logs: this.logs } = await this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- ));
- });
- it('revert if execution comes too early 1/2', async function () {
- await expectRevert(
- this.timelock.execute(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: operation is not ready',
- );
- });
- it('revert if execution comes too early 2/2', async function () {
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
- await time.increaseTo(timestamp - 2); // -1 is too tight, test sometime fails
- await expectRevert(
- this.timelock.execute(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: operation is not ready',
- );
- });
- describe('on time', function () {
- beforeEach(async function () {
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
- await time.increaseTo(timestamp);
- });
- it('executor can reveal', async function () {
- const receipt = await this.timelock.execute(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- );
- expectEvent(receipt, 'CallExecuted', {
- id: this.operation.id,
- index: web3.utils.toBN(0),
- target: this.operation.target,
- value: web3.utils.toBN(this.operation.value),
- data: this.operation.data,
- });
- });
- it('prevent non-executor from revealing', async function () {
- await expectRevert(
- this.timelock.execute(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- { from: other },
- ),
- 'TimelockController: sender requires permission',
- );
- });
- });
- });
- });
- });
- describe('batch', function () {
- describe('schedule', function () {
- beforeEach(async function () {
- this.operation = genOperationBatch(
- Array(8).fill('0xEd912250835c812D4516BBD80BdaEA1bB63a293C'),
- Array(8).fill(0),
- Array(8).fill('0x2fcb7a88'),
- ZERO_BYTES32,
- '0x6cf9d042ade5de78bed9ffd075eb4b2a4f6b1736932c2dc8af517d6e066f51f5',
- );
- });
- it('proposer can schedule', async function () {
- const receipt = await this.timelock.scheduleBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- );
- for (const i in this.operation.targets) {
- expectEvent(receipt, 'CallScheduled', {
- id: this.operation.id,
- index: web3.utils.toBN(i),
- target: this.operation.targets[i],
- value: web3.utils.toBN(this.operation.values[i]),
- data: this.operation.datas[i],
- predecessor: this.operation.predecessor,
- delay: MINDELAY,
- });
- }
- const block = await web3.eth.getBlock(receipt.receipt.blockHash);
- expect(await this.timelock.getTimestamp(this.operation.id))
- .to.be.bignumber.equal(web3.utils.toBN(block.timestamp).add(MINDELAY));
- });
- it('prevent overwritting active operation', async function () {
- await this.timelock.scheduleBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await expectRevert(
- this.timelock.scheduleBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- ),
- 'TimelockController: operation already scheduled',
- );
- });
- it('prevent non-proposer from commiting', async function () {
- await expectRevert(
- this.timelock.scheduleBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: other },
- ),
- 'TimelockController: sender requires permission',
- );
- });
- it('enforce minimum delay', async function () {
- await expectRevert(
- this.timelock.scheduleBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY - 1,
- { from: proposer },
- ),
- 'TimelockController: insufficient delay',
- );
- });
- });
- describe('execute', function () {
- beforeEach(async function () {
- this.operation = genOperationBatch(
- Array(8).fill('0x76E53CcEb05131Ef5248553bEBDb8F70536830b1'),
- Array(8).fill(0),
- Array(8).fill('0x58a60f63'),
- ZERO_BYTES32,
- '0x9545eeabc7a7586689191f78a5532443698538e54211b5bd4d7dc0fc0102b5c7',
- );
- });
- it('revert if operation is not scheduled', async function () {
- await expectRevert(
- this.timelock.executeBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: operation is not ready',
- );
- });
- describe('with scheduled operation', function () {
- beforeEach(async function () {
- ({ receipt: this.receipt, logs: this.logs } = await this.timelock.scheduleBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- ));
- });
- it('revert if execution comes too early 1/2', async function () {
- await expectRevert(
- this.timelock.executeBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: operation is not ready',
- );
- });
- it('revert if execution comes too early 2/2', async function () {
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
- await time.increaseTo(timestamp - 2); // -1 is to tight, test sometime fails
- await expectRevert(
- this.timelock.executeBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: operation is not ready',
- );
- });
- describe('on time', function () {
- beforeEach(async function () {
- const timestamp = await this.timelock.getTimestamp(this.operation.id);
- await time.increaseTo(timestamp);
- });
- it('executor can reveal', async function () {
- const receipt = await this.timelock.executeBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- );
- for (const i in this.operation.targets) {
- expectEvent(receipt, 'CallExecuted', {
- id: this.operation.id,
- index: web3.utils.toBN(i),
- target: this.operation.targets[i],
- value: web3.utils.toBN(this.operation.values[i]),
- data: this.operation.datas[i],
- });
- }
- });
- it('prevent non-executor from revealing', async function () {
- await expectRevert(
- this.timelock.executeBatch(
- this.operation.targets,
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: other },
- ),
- 'TimelockController: sender requires permission',
- );
- });
- it('length mismatch #1', async function () {
- await expectRevert(
- this.timelock.executeBatch(
- [],
- this.operation.values,
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: length mismatch',
- );
- });
- it('length mismatch #2', async function () {
- await expectRevert(
- this.timelock.executeBatch(
- this.operation.targets,
- [],
- this.operation.datas,
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: length mismatch',
- );
- });
- it('length mismatch #3', async function () {
- await expectRevert(
- this.timelock.executeBatch(
- this.operation.targets,
- this.operation.values,
- [],
- this.operation.predecessor,
- this.operation.salt,
- { from: executor },
- ),
- 'TimelockController: length mismatch',
- );
- });
- });
- });
- it('partial execution', async function () {
- const operation = genOperationBatch(
- [
- this.callreceivermock.address,
- this.callreceivermock.address,
- this.callreceivermock.address,
- ],
- [
- 0,
- 0,
- 0,
- ],
- [
- this.callreceivermock.contract.methods.mockFunction().encodeABI(),
- this.callreceivermock.contract.methods.mockFunctionThrows().encodeABI(),
- this.callreceivermock.contract.methods.mockFunction().encodeABI(),
- ],
- ZERO_BYTES32,
- '0x8ac04aa0d6d66b8812fb41d39638d37af0a9ab11da507afd65c509f8ed079d3e',
- );
- await this.timelock.scheduleBatch(
- operation.targets,
- operation.values,
- operation.datas,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- await expectRevert(
- this.timelock.executeBatch(
- operation.targets,
- operation.values,
- operation.datas,
- operation.predecessor,
- operation.salt,
- { from: executor },
- ),
- 'TimelockController: underlying transaction reverted',
- );
- });
- });
- });
- describe('cancel', function () {
- beforeEach(async function () {
- this.operation = genOperation(
- '0xC6837c44AA376dbe1d2709F13879E040CAb653ca',
- 0,
- '0x296e58dd',
- ZERO_BYTES32,
- '0xa2485763600634800df9fc9646fb2c112cf98649c55f63dd1d9c7d13a64399d9',
- );
- ({ receipt: this.receipt, logs: this.logs } = await this.timelock.schedule(
- this.operation.target,
- this.operation.value,
- this.operation.data,
- this.operation.predecessor,
- this.operation.salt,
- MINDELAY,
- { from: proposer },
- ));
- });
- it('proposer can cancel', async function () {
- const receipt = await this.timelock.cancel(this.operation.id, { from: proposer });
- expectEvent(receipt, 'Cancelled', { id: this.operation.id });
- });
- it('prevent non-proposer from canceling', async function () {
- await expectRevert(
- this.timelock.cancel(this.operation.id, { from: other }),
- 'TimelockController: sender requires permission',
- );
- });
- });
- });
- describe('maintenance', function () {
- it('prevent unauthorized maintenance', async function () {
- await expectRevert(
- this.timelock.updateDelay(0, { from: other }),
- 'TimelockController: caller must be timelock',
- );
- });
- it('timelock scheduled maintenance', async function () {
- const newDelay = time.duration.hours(6);
- const operation = genOperation(
- this.timelock.address,
- 0,
- this.timelock.contract.methods.updateDelay(newDelay.toString()).encodeABI(),
- ZERO_BYTES32,
- '0xf8e775b2c5f4d66fb5c7fa800f35ef518c262b6014b3c0aee6ea21bff157f108',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- const receipt = await this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- );
- expectEvent(receipt, 'MinDelayChange', { newDuration: newDelay.toString(), oldDuration: MINDELAY });
- expect(await this.timelock.getMinDelay()).to.be.bignumber.equal(newDelay);
- });
- });
- describe('dependency', function () {
- beforeEach(async function () {
- this.operation1 = genOperation(
- '0xdE66bD4c97304200A95aE0AadA32d6d01A867E39',
- 0,
- '0x01dc731a',
- ZERO_BYTES32,
- '0x64e932133c7677402ead2926f86205e2ca4686aebecf5a8077627092b9bb2feb',
- );
- this.operation2 = genOperation(
- '0x3c7944a3F1ee7fc8c5A5134ba7c79D11c3A1FCa3',
- 0,
- '0x8f531849',
- this.operation1.id,
- '0x036e1311cac523f9548e6461e29fb1f8f9196b91910a41711ea22f5de48df07d',
- );
- await this.timelock.schedule(
- this.operation1.target,
- this.operation1.value,
- this.operation1.data,
- this.operation1.predecessor,
- this.operation1.salt,
- MINDELAY,
- { from: proposer },
- );
- await this.timelock.schedule(
- this.operation2.target,
- this.operation2.value,
- this.operation2.data,
- this.operation2.predecessor,
- this.operation2.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- });
- it('cannot execute before dependency', async function () {
- await expectRevert(
- this.timelock.execute(
- this.operation2.target,
- this.operation2.value,
- this.operation2.data,
- this.operation2.predecessor,
- this.operation2.salt,
- { from: executor },
- ),
- 'TimelockController: missing dependency',
- );
- });
- it('can execute after dependency', async function () {
- await this.timelock.execute(
- this.operation1.target,
- this.operation1.value,
- this.operation1.data,
- this.operation1.predecessor,
- this.operation1.salt,
- { from: executor },
- );
- await this.timelock.execute(
- this.operation2.target,
- this.operation2.value,
- this.operation2.data,
- this.operation2.predecessor,
- this.operation2.salt,
- { from: executor },
- );
- });
- });
- describe('usage scenario', function () {
- this.timeout(10000);
- it('call', async function () {
- const operation = genOperation(
- this.implementation2.address,
- 0,
- this.implementation2.contract.methods.setValue(42).encodeABI(),
- ZERO_BYTES32,
- '0x8043596363daefc89977b25f9d9b4d06c3910959ef0c4d213557a903e1b555e2',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- await this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- );
- expect(await this.implementation2.getValue()).to.be.bignumber.equal(web3.utils.toBN(42));
- });
- it('call reverting', async function () {
- const operation = genOperation(
- this.callreceivermock.address,
- 0,
- this.callreceivermock.contract.methods.mockFunctionRevertsNoReason().encodeABI(),
- ZERO_BYTES32,
- '0xb1b1b276fdf1a28d1e00537ea73b04d56639128b08063c1a2f70a52e38cba693',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- await expectRevert(
- this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- ),
- 'TimelockController: underlying transaction reverted',
- );
- });
- it('call throw', async function () {
- const operation = genOperation(
- this.callreceivermock.address,
- 0,
- this.callreceivermock.contract.methods.mockFunctionThrows().encodeABI(),
- ZERO_BYTES32,
- '0xe5ca79f295fc8327ee8a765fe19afb58f4a0cbc5053642bfdd7e73bc68e0fc67',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- await expectRevert(
- this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- ),
- 'TimelockController: underlying transaction reverted',
- );
- });
- // Skipped in a coverage mode due to coverage mode setting a block gas limit to 0xffffffffff
- // which cause a mockFunctionOutOfGas function to crash Ganache and the
- // subsequent tests before running out of gas.
- it('call out of gas', async function () {
- if (config.coverage) { return this.skip(); }
- const operation = genOperation(
- this.callreceivermock.address,
- 0,
- this.callreceivermock.contract.methods.mockFunctionOutOfGas().encodeABI(),
- ZERO_BYTES32,
- '0xf3274ce7c394c5b629d5215723563a744b817e1730cca5587c567099a14578fd',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- await time.increase(MINDELAY);
- await expectRevert(
- this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- ),
- 'TimelockController: underlying transaction reverted',
- );
- });
- it('call payable with eth', async function () {
- const operation = genOperation(
- this.callreceivermock.address,
- 1,
- this.callreceivermock.contract.methods.mockFunction().encodeABI(),
- ZERO_BYTES32,
- '0x5ab73cd33477dcd36c1e05e28362719d0ed59a7b9ff14939de63a43073dc1f44',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- 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.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
- await this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { 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.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(1));
- });
- it('call nonpayable with eth', async function () {
- const operation = genOperation(
- this.callreceivermock.address,
- 1,
- this.callreceivermock.contract.methods.mockFunctionNonPayable().encodeABI(),
- ZERO_BYTES32,
- '0xb78edbd920c7867f187e5aa6294ae5a656cfbf0dea1ccdca3751b740d0f2bdf8',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- 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.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
- await expectRevert(
- this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- ),
- '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.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
- });
- it('call reverting with eth', async function () {
- const operation = genOperation(
- this.callreceivermock.address,
- 1,
- this.callreceivermock.contract.methods.mockFunctionRevertsNoReason().encodeABI(),
- ZERO_BYTES32,
- '0xdedb4563ef0095db01d81d3f2decf57cf83e4a72aa792af14c43a792b56f4de6',
- );
- await this.timelock.schedule(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- MINDELAY,
- { from: proposer },
- );
- 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.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
- await expectRevert(
- this.timelock.execute(
- operation.target,
- operation.value,
- operation.data,
- operation.predecessor,
- operation.salt,
- { from: executor },
- ),
- '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.callreceivermock.address)).to.be.bignumber.equal(web3.utils.toBN(0));
- });
- });
- });
|