Add Initialized event (#3294)
Co-authored-by: Francisco Giordano <frangio.1@gmail.com>
This commit is contained in:
@ -16,6 +16,8 @@
|
|||||||
* `ERC20Wrapper`: the `decimals()` function now tries to fetch the value from the underlying token instance. If that calls revert, then the default value is used. ([#3259](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3259))
|
* `ERC20Wrapper`: the `decimals()` function now tries to fetch the value from the underlying token instance. If that calls revert, then the default value is used. ([#3259](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3259))
|
||||||
* `Governor`: Implement `IERC721Receiver` and `IERC1155Receiver` to improve token custody by governors. ([#3230](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3230))
|
* `Governor`: Implement `IERC721Receiver` and `IERC1155Receiver` to improve token custody by governors. ([#3230](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3230))
|
||||||
* `TimelockController`: Implement `IERC721Receiver` and `IERC1155Receiver` to improve token custody by timelocks. ([#3230](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3230))
|
* `TimelockController`: Implement `IERC721Receiver` and `IERC1155Receiver` to improve token custody by timelocks. ([#3230](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3230))
|
||||||
|
* `Initializable`: add a reinitializer modifier that enables the initialization of new modules, added to already initialized contracts through upgradeability. ([#3232](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3232))
|
||||||
|
* `Initializable`: add an Initialized event that tracks initialized version numbers. ([#3294](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3294))
|
||||||
|
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
|
|
||||||
|
|||||||
@ -66,6 +66,11 @@ abstract contract Initializable {
|
|||||||
*/
|
*/
|
||||||
bool private _initializing;
|
bool private _initializing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Triggered when the contract has been initialized or reinitialized.
|
||||||
|
*/
|
||||||
|
event Initialized(uint8 version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
|
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
|
||||||
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
|
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
|
||||||
@ -78,6 +83,7 @@ abstract contract Initializable {
|
|||||||
_;
|
_;
|
||||||
if (isTopLevelCall) {
|
if (isTopLevelCall) {
|
||||||
_initializing = false;
|
_initializing = false;
|
||||||
|
emit Initialized(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +107,7 @@ abstract contract Initializable {
|
|||||||
_;
|
_;
|
||||||
if (isTopLevelCall) {
|
if (isTopLevelCall) {
|
||||||
_initializing = false;
|
_initializing = false;
|
||||||
|
emit Initialized(version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const { expectRevert } = require('@openzeppelin/test-helpers');
|
const { expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
|
||||||
const { expect } = require('chai');
|
const { expect } = require('chai');
|
||||||
|
|
||||||
const InitializableMock = artifacts.require('InitializableMock');
|
const InitializableMock = artifacts.require('InitializableMock');
|
||||||
@ -12,13 +12,13 @@ contract('Initializable', function (accounts) {
|
|||||||
this.contract = await InitializableMock.new();
|
this.contract = await InitializableMock.new();
|
||||||
});
|
});
|
||||||
|
|
||||||
context('before initialize', function () {
|
describe('before initialize', function () {
|
||||||
it('initializer has not run', async function () {
|
it('initializer has not run', async function () {
|
||||||
expect(await this.contract.initializerRan()).to.equal(false);
|
expect(await this.contract.initializerRan()).to.equal(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context('after initialize', function () {
|
describe('after initialize', function () {
|
||||||
beforeEach('initializing', async function () {
|
beforeEach('initializing', async function () {
|
||||||
await this.contract.initialize();
|
await this.contract.initialize();
|
||||||
});
|
});
|
||||||
@ -32,7 +32,7 @@ contract('Initializable', function (accounts) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context('nested under an initializer', function () {
|
describe('nested under an initializer', function () {
|
||||||
it('initializer modifier reverts', async function () {
|
it('initializer modifier reverts', async function () {
|
||||||
await expectRevert(this.contract.initializerNested(), 'Initializable: contract is already initialized');
|
await expectRevert(this.contract.initializerNested(), 'Initializable: contract is already initialized');
|
||||||
});
|
});
|
||||||
@ -108,6 +108,39 @@ contract('Initializable', function (accounts) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('events', function () {
|
||||||
|
it('constructor initialization emits event', async function () {
|
||||||
|
const contract = await ConstructorInitializableMock.new();
|
||||||
|
|
||||||
|
await expectEvent.inTransaction(contract.transactionHash, contract, 'Initialized', { version: '1' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('initialization emits event', async function () {
|
||||||
|
const contract = await ReinitializerMock.new();
|
||||||
|
|
||||||
|
const { receipt } = await contract.initialize();
|
||||||
|
expect(receipt.logs.filter(({ event }) => event === 'Initialized').length).to.be.equal(1);
|
||||||
|
expectEvent(receipt, 'Initialized', { version: '1' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reinitialization emits event', async function () {
|
||||||
|
const contract = await ReinitializerMock.new();
|
||||||
|
|
||||||
|
const { receipt } = await contract.reinitialize(128);
|
||||||
|
expect(receipt.logs.filter(({ event }) => event === 'Initialized').length).to.be.equal(1);
|
||||||
|
expectEvent(receipt, 'Initialized', { version: '128' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('chained reinitialization emits multiple events', async function () {
|
||||||
|
const contract = await ReinitializerMock.new();
|
||||||
|
|
||||||
|
const { receipt } = await contract.chainReinitialize(2, 3);
|
||||||
|
expect(receipt.logs.filter(({ event }) => event === 'Initialized').length).to.be.equal(2);
|
||||||
|
expectEvent(receipt, 'Initialized', { version: '2' });
|
||||||
|
expectEvent(receipt, 'Initialized', { version: '3' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('complex testing with inheritance', function () {
|
describe('complex testing with inheritance', function () {
|
||||||
const mother = '12';
|
const mother = '12';
|
||||||
const gramps = '56';
|
const gramps = '56';
|
||||||
|
|||||||
Reference in New Issue
Block a user