Finalize test migration: remove legacy dependencies and test helpers (#4797)

This commit is contained in:
Hadrien Croubois
2023-12-26 23:46:06 +01:00
committed by GitHub
parent abcf9dd8b7
commit a72c9561b9
96 changed files with 951 additions and 6503 deletions

View File

@ -2,7 +2,7 @@ const { ethers } = require('hardhat');
const { expect } = require('chai');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { getAddressInSlot, setSlot, ImplementationSlot, AdminSlot, BeaconSlot } = require('../../helpers/erc1967');
const { getAddressInSlot, setSlot, ImplementationSlot, AdminSlot, BeaconSlot } = require('../../helpers/storage');
async function fixture() {
const [, admin, anotherAccount] = await ethers.getSigners();
@ -26,8 +26,8 @@ describe('ERC1967Utils', function () {
describe('getImplementation', function () {
it('returns current implementation and matches implementation slot value', async function () {
expect(await this.utils.$getImplementation()).to.equal(this.v1.target);
expect(await getAddressInSlot(this.utils, ImplementationSlot)).to.equal(this.v1.target);
expect(await this.utils.$getImplementation()).to.equal(this.v1);
expect(await getAddressInSlot(this.utils, ImplementationSlot)).to.equal(this.v1);
});
});
@ -36,14 +36,14 @@ describe('ERC1967Utils', function () {
const newImplementation = this.v2;
const tx = await this.utils.$upgradeToAndCall(newImplementation, '0x');
expect(await getAddressInSlot(this.utils, ImplementationSlot)).to.equal(newImplementation.target);
await expect(tx).to.emit(this.utils, 'Upgraded').withArgs(newImplementation.target);
expect(await getAddressInSlot(this.utils, ImplementationSlot)).to.equal(newImplementation);
await expect(tx).to.emit(this.utils, 'Upgraded').withArgs(newImplementation);
});
it('reverts when implementation does not contain code', async function () {
await expect(this.utils.$upgradeToAndCall(this.anotherAccount, '0x'))
.to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidImplementation')
.withArgs(this.anotherAccount.address);
.withArgs(this.anotherAccount);
});
describe('when data is empty', function () {
@ -72,8 +72,8 @@ describe('ERC1967Utils', function () {
describe('getAdmin', function () {
it('returns current admin and matches admin slot value', async function () {
expect(await this.utils.$getAdmin()).to.equal(this.admin.address);
expect(await getAddressInSlot(this.utils, AdminSlot)).to.equal(this.admin.address);
expect(await this.utils.$getAdmin()).to.equal(this.admin);
expect(await getAddressInSlot(this.utils, AdminSlot)).to.equal(this.admin);
});
});
@ -82,8 +82,8 @@ describe('ERC1967Utils', function () {
const newAdmin = this.anotherAccount;
const tx = await this.utils.$changeAdmin(newAdmin);
expect(await getAddressInSlot(this.utils, AdminSlot)).to.equal(newAdmin.address);
await expect(tx).to.emit(this.utils, 'AdminChanged').withArgs(this.admin.address, newAdmin.address);
expect(await getAddressInSlot(this.utils, AdminSlot)).to.equal(newAdmin);
await expect(tx).to.emit(this.utils, 'AdminChanged').withArgs(this.admin, newAdmin);
});
it('reverts when setting the address zero as admin', async function () {
@ -102,8 +102,8 @@ describe('ERC1967Utils', function () {
describe('getBeacon', function () {
it('returns current beacon and matches beacon slot value', async function () {
expect(await this.utils.$getBeacon()).to.equal(this.beacon.target);
expect(await getAddressInSlot(this.utils, BeaconSlot)).to.equal(this.beacon.target);
expect(await this.utils.$getBeacon()).to.equal(this.beacon);
expect(await getAddressInSlot(this.utils, BeaconSlot)).to.equal(this.beacon);
});
});
@ -112,14 +112,14 @@ describe('ERC1967Utils', function () {
const newBeacon = await ethers.deployContract('UpgradeableBeaconMock', [this.v2]);
const tx = await this.utils.$upgradeBeaconToAndCall(newBeacon, '0x');
expect(await getAddressInSlot(this.utils, BeaconSlot)).to.equal(newBeacon.target);
await expect(tx).to.emit(this.utils, 'BeaconUpgraded').withArgs(newBeacon.target);
expect(await getAddressInSlot(this.utils, BeaconSlot)).to.equal(newBeacon);
await expect(tx).to.emit(this.utils, 'BeaconUpgraded').withArgs(newBeacon);
});
it('reverts when beacon does not contain code', async function () {
await expect(this.utils.$upgradeBeaconToAndCall(this.anotherAccount, '0x'))
.to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidBeacon')
.withArgs(this.anotherAccount.address);
.withArgs(this.anotherAccount);
});
it("reverts when beacon's implementation does not contain code", async function () {
@ -127,7 +127,7 @@ describe('ERC1967Utils', function () {
await expect(this.utils.$upgradeBeaconToAndCall(newBeacon, '0x'))
.to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidImplementation')
.withArgs(this.anotherAccount.address);
.withArgs(this.anotherAccount);
});
describe('when data is empty', function () {
@ -154,7 +154,7 @@ describe('ERC1967Utils', function () {
const newBeacon = await ethers.deployContract('UpgradeableBeaconReentrantMock');
await expect(this.utils.$upgradeBeaconToAndCall(newBeacon, '0x'))
.to.be.revertedWithCustomError(newBeacon, 'BeaconProxyBeaconSlotAddress')
.withArgs(newBeacon.target);
.withArgs(newBeacon);
});
});
});

View File

@ -1,19 +1,19 @@
const { ethers } = require('hardhat');
const { expect } = require('chai');
const { getAddressInSlot, ImplementationSlot } = require('../helpers/erc1967');
const { getAddressInSlot, ImplementationSlot } = require('../helpers/storage');
module.exports = function shouldBehaveLikeProxy() {
it('cannot be initialized with a non-contract address', async function () {
const initializeData = '0x';
await expect(this.createProxy(this.nonContractAddress, initializeData))
.to.be.revertedWithCustomError(await ethers.getContractFactory('ERC1967Proxy'), 'ERC1967InvalidImplementation')
.withArgs(this.nonContractAddress.address);
.withArgs(this.nonContractAddress);
});
const assertProxyInitialization = function ({ value, balance }) {
it('sets the implementation address', async function () {
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.implementation.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.implementation);
});
it('initializes the proxy', async function () {

View File

@ -1,7 +1,8 @@
const { ethers } = require('hardhat');
const { expect } = require('chai');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { getAddressInSlot, BeaconSlot } = require('../../helpers/erc1967');
const { getAddressInSlot, BeaconSlot } = require('../../helpers/storage');
async function fixture() {
const [admin, other] = await ethers.getSigners();
@ -27,7 +28,7 @@ describe('BeaconProxy', function () {
await expect(this.newBeaconProxy(notBeacon, '0x'))
.to.be.revertedWithCustomError(this.factory, 'ERC1967InvalidBeacon')
.withArgs(notBeacon.address);
.withArgs(notBeacon);
});
it('non-compliant beacon', async function () {
@ -48,7 +49,7 @@ describe('BeaconProxy', function () {
describe('initialization', function () {
async function assertInitialized({ value, balance }) {
const beaconAddress = await getAddressInSlot(this.proxy, BeaconSlot);
expect(beaconAddress).to.equal(this.beacon.target);
expect(beaconAddress).to.equal(this.beacon);
const dummy = this.v1.attach(this.proxy);
expect(await dummy.value()).to.equal(value);

View File

@ -20,36 +20,36 @@ describe('UpgradeableBeacon', function () {
it('cannot be created with non-contract implementation', async function () {
await expect(ethers.deployContract('UpgradeableBeacon', [this.other, this.admin]))
.to.be.revertedWithCustomError(this.beacon, 'BeaconInvalidImplementation')
.withArgs(this.other.address);
.withArgs(this.other);
});
describe('once deployed', async function () {
it('emits Upgraded event to the first implementation', async function () {
await expect(this.beacon.deploymentTransaction()).to.emit(this.beacon, 'Upgraded').withArgs(this.v1.target);
await expect(this.beacon.deploymentTransaction()).to.emit(this.beacon, 'Upgraded').withArgs(this.v1);
});
it('returns implementation', async function () {
expect(await this.beacon.implementation()).to.equal(this.v1.target);
expect(await this.beacon.implementation()).to.equal(this.v1);
});
it('can be upgraded by the admin', async function () {
await expect(this.beacon.connect(this.admin).upgradeTo(this.v2))
.to.emit(this.beacon, 'Upgraded')
.withArgs(this.v2.target);
.withArgs(this.v2);
expect(await this.beacon.implementation()).to.equal(this.v2.target);
expect(await this.beacon.implementation()).to.equal(this.v2);
});
it('cannot be upgraded to a non-contract', async function () {
await expect(this.beacon.connect(this.admin).upgradeTo(this.other))
.to.be.revertedWithCustomError(this.beacon, 'BeaconInvalidImplementation')
.withArgs(this.other.address);
.withArgs(this.other);
});
it('cannot be upgraded by other account', async function () {
await expect(this.beacon.connect(this.other).upgradeTo(this.v2))
.to.be.revertedWithCustomError(this.beacon, 'OwnableUnauthorizedAccount')
.withArgs(this.other.address);
.withArgs(this.other);
});
});
});

View File

@ -1,7 +1,8 @@
const { ethers } = require('hardhat');
const { expect } = require('chai');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { getAddressInSlot, ImplementationSlot } = require('../../helpers/erc1967');
const { getAddressInSlot, ImplementationSlot } = require('../../helpers/storage');
async function fixture() {
const [admin, other] = await ethers.getSigners();
@ -27,7 +28,7 @@ describe('ProxyAdmin', function () {
});
it('has an owner', async function () {
expect(await this.proxyAdmin.owner()).to.equal(this.admin.address);
expect(await this.proxyAdmin.owner()).to.equal(this.admin);
});
it('has an interface version', async function () {
@ -39,14 +40,14 @@ describe('ProxyAdmin', function () {
it('fails to upgrade', async function () {
await expect(this.proxyAdmin.connect(this.other).upgradeAndCall(this.proxy, this.v2, '0x'))
.to.be.revertedWithCustomError(this.proxyAdmin, 'OwnableUnauthorizedAccount')
.withArgs(this.other.address);
.withArgs(this.other);
});
});
context('with authorized account', function () {
it('upgrades implementation', async function () {
await this.proxyAdmin.connect(this.admin).upgradeAndCall(this.proxy, this.v2, '0x');
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.be.equal(this.v2.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.be.equal(this.v2);
});
});
});
@ -57,7 +58,7 @@ describe('ProxyAdmin', function () {
const data = this.v1.interface.encodeFunctionData('initializeNonPayableWithValue', [1337n]);
await expect(this.proxyAdmin.connect(this.other).upgradeAndCall(this.proxy, this.v2, data))
.to.be.revertedWithCustomError(this.proxyAdmin, 'OwnableUnauthorizedAccount')
.withArgs(this.other.address);
.withArgs(this.other);
});
});
@ -73,7 +74,7 @@ describe('ProxyAdmin', function () {
it('upgrades implementation', async function () {
const data = this.v2.interface.encodeFunctionData('initializeNonPayableWithValue', [1337n]);
await this.proxyAdmin.connect(this.admin).upgradeAndCall(this.proxy, this.v2, data);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.be.equal(this.v2.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.be.equal(this.v2);
});
});
});

View File

@ -1,8 +1,8 @@
const { ethers } = require('hardhat');
const { expect } = require('chai');
const { getAddressInSlot, ImplementationSlot, AdminSlot } = require('../../helpers/erc1967');
const { impersonate } = require('../../helpers/account');
const { getAddressInSlot, ImplementationSlot, AdminSlot } = require('../../helpers/storage');
// createProxy, initialOwner, accounts
module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
@ -43,7 +43,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
describe('implementation', function () {
it('returns the current implementation address', async function () {
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.implementationV0.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.implementationV0);
});
it('delegates to the implementation', async function () {
@ -53,26 +53,26 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
describe('proxy admin', function () {
it('emits AdminChanged event during construction', async function () {
await expect(this.tx).to.emit(this.proxy, 'AdminChanged').withArgs(ethers.ZeroAddress, this.proxyAdmin.target);
await expect(this.tx).to.emit(this.proxy, 'AdminChanged').withArgs(ethers.ZeroAddress, this.proxyAdmin);
});
it('sets the proxy admin in storage with the correct initial owner', async function () {
expect(await getAddressInSlot(this.proxy, AdminSlot)).to.equal(this.proxyAdmin.target);
expect(await getAddressInSlot(this.proxy, AdminSlot)).to.equal(this.proxyAdmin);
expect(await this.proxyAdmin.owner()).to.equal(this.owner.address);
expect(await this.proxyAdmin.owner()).to.equal(this.owner);
});
it('can overwrite the admin by the implementation', async function () {
await this.instance.unsafeOverrideAdmin(this.other);
const ERC1967AdminSlotValue = await getAddressInSlot(this.proxy, AdminSlot);
expect(ERC1967AdminSlotValue).to.equal(this.other.address);
expect(ERC1967AdminSlotValue).to.not.equal(this.proxyAdmin.address);
expect(ERC1967AdminSlotValue).to.equal(this.other);
expect(ERC1967AdminSlotValue).to.not.equal(this.proxyAdmin);
// Still allows previous admin to execute admin operations
await expect(this.proxy.connect(this.proxyAdminAsSigner).upgradeToAndCall(this.implementationV1, '0x'))
.to.emit(this.proxy, 'Upgraded')
.withArgs(this.implementationV1.target);
.withArgs(this.implementationV1);
});
});
@ -99,11 +99,11 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
});
it('upgrades to the requested implementation', async function () {
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behavior.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behavior);
});
it('emits an event', async function () {
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behavior.target);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behavior);
});
it('calls the initializer function', async function () {
@ -160,9 +160,9 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
});
it('upgrades to the requested version and emits an event', async function () {
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV1.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV1);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV1.target);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV1);
});
it("calls the 'initialize' function and sends given value to the proxy", async function () {
@ -184,9 +184,9 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
});
it('upgrades to the requested version and emits an event', async function () {
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV2.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV2);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV2.target);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV2);
});
it("calls the 'migrate' function and sends given value to the proxy", async function () {
@ -209,9 +209,9 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
});
it('upgrades to the requested version and emits an event', async function () {
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV3.target);
expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV3);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV3.target);
await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV3);
});
it("calls the 'migrate' function and sends given value to the proxy", async function () {
@ -255,7 +255,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
it('executes the proxy function if the sender is the admin', async function () {
await expect(this.proxy.connect(this.proxyAdminAsSigner).upgradeToAndCall(this.clashingImplV1, '0x'))
.to.emit(this.proxy, 'Upgraded')
.withArgs(this.clashingImplV1.target);
.withArgs(this.clashingImplV1);
});
it('delegates the call to implementation when sender is not the admin', async function () {

View File

@ -2,7 +2,7 @@ const { ethers } = require('hardhat');
const { expect } = require('chai');
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
const { getAddressInSlot, ImplementationSlot } = require('../../helpers/erc1967');
const { getAddressInSlot, ImplementationSlot } = require('../../helpers/storage');
async function fixture() {
const implInitial = await ethers.deployContract('UUPSUpgradeableMock');
@ -40,9 +40,9 @@ describe('UUPSUpgradeable', function () {
it('upgrade to upgradeable implementation', async function () {
await expect(this.instance.upgradeToAndCall(this.implUpgradeOk, '0x'))
.to.emit(this.instance, 'Upgraded')
.withArgs(this.implUpgradeOk.target);
.withArgs(this.implUpgradeOk);
expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeOk.target);
expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeOk);
});
it('upgrade to upgradeable implementation with call', async function () {
@ -52,9 +52,9 @@ describe('UUPSUpgradeable', function () {
this.instance.upgradeToAndCall(this.implUpgradeOk, this.implUpgradeOk.interface.encodeFunctionData('increment')),
)
.to.emit(this.instance, 'Upgraded')
.withArgs(this.implUpgradeOk.target);
.withArgs(this.implUpgradeOk);
expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeOk.target);
expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeOk);
expect(await this.instance.current()).to.equal(1n);
});
@ -96,16 +96,16 @@ describe('UUPSUpgradeable', function () {
it('upgrade to and unsafe upgradeable implementation', async function () {
await expect(this.instance.upgradeToAndCall(this.implUpgradeUnsafe, '0x'))
.to.emit(this.instance, 'Upgraded')
.withArgs(this.implUpgradeUnsafe.target);
.withArgs(this.implUpgradeUnsafe);
expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeUnsafe.target);
expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeUnsafe);
});
// delegate to a non existing upgradeTo function causes a low level revert
it('reject upgrade to non uups implementation', async function () {
await expect(this.instance.upgradeToAndCall(this.implUpgradeNonUUPS, '0x'))
.to.be.revertedWithCustomError(this.instance, 'ERC1967InvalidImplementation')
.withArgs(this.implUpgradeNonUUPS.target);
.withArgs(this.implUpgradeNonUUPS);
});
it('reject proxy address as implementation', async function () {
@ -115,6 +115,6 @@ describe('UUPSUpgradeable', function () {
await expect(this.instance.upgradeToAndCall(otherInstance, '0x'))
.to.be.revertedWithCustomError(this.instance, 'ERC1967InvalidImplementation')
.withArgs(otherInstance.target);
.withArgs(otherInstance);
});
});