Update docs

This commit is contained in:
github-actions
2023-05-09 19:56:30 +00:00
parent 47e38c7bda
commit 6ae39c4dc1
579 changed files with 30453 additions and 21485 deletions

View File

@ -4,7 +4,7 @@ const { expect } = require('chai');
const DummyImplementation = artifacts.require('DummyImplementation');
module.exports = function shouldBehaveLikeClone (createClone) {
module.exports = function shouldBehaveLikeClone(createClone) {
before('deploy implementation', async function () {
this.implementation = web3.utils.toChecksumAddress((await DummyImplementation.new()).address);
});
@ -27,9 +27,7 @@ module.exports = function shouldBehaveLikeClone (createClone) {
describe('when not sending balance', function () {
beforeEach('creating proxy', async function () {
this.proxy = (
await createClone(this.implementation, initializeData)
).address;
this.proxy = (await createClone(this.implementation, initializeData)).address;
});
assertProxyInitialization({
@ -42,9 +40,7 @@ module.exports = function shouldBehaveLikeClone (createClone) {
const value = 10e5;
it('reverts', async function () {
await expectRevert.unspecified(
createClone(this.implementation, initializeData, { value }),
);
await expectRevert.unspecified(createClone(this.implementation, initializeData, { value }));
});
});
});
@ -55,9 +51,7 @@ module.exports = function shouldBehaveLikeClone (createClone) {
describe('when not sending balance', function () {
beforeEach('creating proxy', async function () {
this.proxy = (
await createClone(this.implementation, initializeData)
).address;
this.proxy = (await createClone(this.implementation, initializeData)).address;
});
assertProxyInitialization({
@ -70,9 +64,7 @@ module.exports = function shouldBehaveLikeClone (createClone) {
const value = 10e5;
beforeEach('creating proxy', async function () {
this.proxy = (
await createClone(this.implementation, initializeData, { value })
).address;
this.proxy = (await createClone(this.implementation, initializeData, { value })).address;
});
assertProxyInitialization({
@ -86,14 +78,13 @@ module.exports = function shouldBehaveLikeClone (createClone) {
describe('initialization with parameters', function () {
describe('non payable', function () {
const expectedInitializedValue = 10;
const initializeData = new DummyImplementation('').contract
.methods.initializeNonPayableWithValue(expectedInitializedValue).encodeABI();
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;
this.proxy = (await createClone(this.implementation, initializeData)).address;
});
assertProxyInitialization({
@ -106,23 +97,20 @@ module.exports = function shouldBehaveLikeClone (createClone) {
const value = 10e5;
it('reverts', async function () {
await expectRevert.unspecified(
createClone(this.implementation, initializeData, { value }),
);
await expectRevert.unspecified(createClone(this.implementation, initializeData, { value }));
});
});
});
describe('payable', function () {
const expectedInitializedValue = 42;
const initializeData = new DummyImplementation('').contract
.methods.initializePayableWithValue(expectedInitializedValue).encodeABI();
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;
this.proxy = (await createClone(this.implementation, initializeData)).address;
});
assertProxyInitialization({
@ -135,9 +123,7 @@ module.exports = function shouldBehaveLikeClone (createClone) {
const value = 10e5;
beforeEach('creating proxy', async function () {
this.proxy = (
await createClone(this.implementation, initializeData, { value })
).address;
this.proxy = (await createClone(this.implementation, initializeData, { value })).address;
});
assertProxyInitialization({

View File

@ -4,14 +4,17 @@ const { expect } = require('chai');
const shouldBehaveLikeClone = require('./Clones.behaviour');
const ClonesMock = artifacts.require('ClonesMock');
const Clones = artifacts.require('$Clones');
contract('Clones', function (accounts) {
const [deployer] = 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;
const factory = await Clones.new();
const receipt = await factory.$clone(implementation);
const address = receipt.logs.find(({ event }) => event === 'return$clone').args.instance;
await web3.eth.sendTransaction({ from: deployer, to: address, value: opts.value, data: initData });
return { address };
});
});
@ -19,33 +22,28 @@ contract('Clones', function (accounts) {
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;
const factory = await Clones.new();
const receipt = await factory.$cloneDeterministic(implementation, salt);
const address = receipt.logs.find(({ event }) => event === 'return$cloneDeterministic').args.instance;
await web3.eth.sendTransaction({ from: deployer, to: address, value: opts.value, data: initData });
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();
const factory = await Clones.new();
// deploy once
expectEvent(
await factory.cloneDeterministic(implementation, salt, '0x'),
'NewInstance',
);
expectEvent(await factory.$cloneDeterministic(implementation, salt), 'return$cloneDeterministic');
// deploy twice
await expectRevert(
factory.cloneDeterministic(implementation, salt, '0x'),
'ERC1167: create2 failed',
);
await expectRevert(factory.$cloneDeterministic(implementation, salt), '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);
const factory = await Clones.new();
const predicted = await factory.$predictDeterministicAddress(implementation, salt);
const creationCode = [
'0x3d602d80600a3d3981f3363d3d373d3d3d363d73',
@ -53,17 +51,11 @@ contract('Clones', function (accounts) {
'5af43d82803e903d91602b57fd5bf3',
].join('');
expect(computeCreate2Address(
salt,
creationCode,
factory.address,
)).to.be.equal(predicted);
expect(computeCreate2Address(salt, creationCode, factory.address)).to.be.equal(predicted);
expectEvent(
await factory.cloneDeterministic(implementation, salt, '0x'),
'NewInstance',
{ instance: predicted },
);
expectEvent(await factory.$cloneDeterministic(implementation, salt), 'return$cloneDeterministic', {
instance: predicted,
});
});
});
});

View File

@ -5,7 +5,7 @@ const { expect } = require('chai');
const DummyImplementation = artifacts.require('DummyImplementation');
module.exports = function shouldBehaveLikeProxy (createProxy, proxyAdminAddress, proxyCreator) {
module.exports = function shouldBehaveLikeProxy(createProxy, proxyAdminAddress, proxyCreator) {
it('cannot be initialized with a non-contract address', async function () {
const nonContractAddress = proxyCreator;
const initializeData = Buffer.from('');
@ -141,8 +141,9 @@ module.exports = function shouldBehaveLikeProxy (createProxy, proxyAdminAddress,
describe('initialization with parameters', function () {
describe('non payable', function () {
const expectedInitializedValue = 10;
const initializeData = new DummyImplementation('').contract
.methods.initializeNonPayableWithValue(expectedInitializedValue).encodeABI();
const initializeData = new DummyImplementation('').contract.methods
.initializeNonPayableWithValue(expectedInitializedValue)
.encodeABI();
describe('when not sending balance', function () {
beforeEach('creating proxy', async function () {
@ -172,8 +173,9 @@ module.exports = function shouldBehaveLikeProxy (createProxy, proxyAdminAddress,
describe('payable', function () {
const expectedInitializedValue = 42;
const initializeData = new DummyImplementation('').contract
.methods.initializePayableWithValue(expectedInitializedValue).encodeABI();
const initializeData = new DummyImplementation('').contract.methods
.initializePayableWithValue(expectedInitializedValue)
.encodeABI();
describe('when not sending balance', function () {
beforeEach('creating proxy', async function () {
@ -210,8 +212,7 @@ module.exports = function shouldBehaveLikeProxy (createProxy, proxyAdminAddress,
});
describe('reverting initialization', function () {
const initializeData = new DummyImplementation('').contract
.methods.reverts().encodeABI();
const initializeData = new DummyImplementation('').contract.methods.reverts().encodeABI();
it('reverts', async function () {
await expectRevert(

View File

@ -15,25 +15,17 @@ contract('BeaconProxy', function (accounts) {
describe('bad beacon is not accepted', async function () {
it('non-contract beacon', async function () {
await expectRevert(
BeaconProxy.new(anotherAccount, '0x'),
'ERC1967: new beacon is not a contract',
);
await expectRevert(BeaconProxy.new(anotherAccount, '0x'), 'ERC1967: new beacon is not a contract');
});
it('non-compliant beacon', async function () {
const beacon = await BadBeaconNoImpl.new();
await expectRevert.unspecified(
BeaconProxy.new(beacon.address, '0x'),
);
await expectRevert.unspecified(BeaconProxy.new(beacon.address, '0x'));
});
it('non-contract implementation', async function () {
const beacon = await BadBeaconNotContract.new();
await expectRevert(
BeaconProxy.new(beacon.address, '0x'),
'ERC1967: beacon implementation is not a contract',
);
await expectRevert(BeaconProxy.new(beacon.address, '0x'), 'ERC1967: beacon implementation is not a contract');
});
});
@ -69,18 +61,14 @@ contract('BeaconProxy', function (accounts) {
it('non-payable initialization', async function () {
const value = '55';
const data = this.implementationV0.contract.methods
.initializeNonPayableWithValue(value)
.encodeABI();
const data = this.implementationV0.contract.methods.initializeNonPayableWithValue(value).encodeABI();
this.proxy = await BeaconProxy.new(this.beacon.address, data);
await this.assertInitialized({ value, balance: '0' });
});
it('payable initialization', async function () {
const value = '55';
const data = this.implementationV0.contract.methods
.initializePayableWithValue(value)
.encodeABI();
const data = this.implementationV0.contract.methods.initializePayableWithValue(value).encodeABI();
const balance = '100';
this.proxy = await BeaconProxy.new(this.beacon.address, data, { value: balance });
await this.assertInitialized({ value, balance });
@ -88,10 +76,7 @@ contract('BeaconProxy', function (accounts) {
it('reverting initialization', async function () {
const data = this.implementationV0.contract.methods.reverts().encodeABI();
await expectRevert(
BeaconProxy.new(this.beacon.address, data),
'DummyImplementation reverted',
);
await expectRevert(BeaconProxy.new(this.beacon.address, data), 'DummyImplementation reverted');
});
});
@ -99,9 +84,7 @@ contract('BeaconProxy', function (accounts) {
const beacon = await UpgradeableBeacon.new(this.implementationV0.address);
const value = '10';
const data = this.implementationV0.contract.methods
.initializeNonPayableWithValue(value)
.encodeABI();
const data = this.implementationV0.contract.methods.initializeNonPayableWithValue(value).encodeABI();
const proxy = await BeaconProxy.new(beacon.address, data);
const dummy = new DummyImplementation(proxy.address);

View File

@ -9,10 +9,7 @@ contract('UpgradeableBeacon', function (accounts) {
const [owner, other] = accounts;
it('cannot be created with non-contract implementation', async function () {
await expectRevert(
UpgradeableBeacon.new(accounts[0]),
'UpgradeableBeacon: implementation is not a contract',
);
await expectRevert(UpgradeableBeacon.new(accounts[0]), 'UpgradeableBeacon: implementation is not a contract');
});
context('once deployed', async function () {
@ -41,10 +38,7 @@ contract('UpgradeableBeacon', function (accounts) {
it('cannot be upgraded by other account', async function () {
const v2 = await Implementation2.new();
await expectRevert(
this.beacon.upgradeTo(v2.address, { from: other }),
'Ownable: caller is not the owner',
);
await expectRevert(this.beacon.upgradeTo(v2.address, { from: other }), 'Ownable: caller is not the owner');
});
});
});

View File

@ -92,9 +92,9 @@ contract('ProxyAdmin', function (accounts) {
it('fails to upgrade', async function () {
const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
await expectRevert(
this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData,
{ from: anotherAccount },
),
this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
from: anotherAccount,
}),
'caller is not the owner',
);
});
@ -105,9 +105,9 @@ contract('ProxyAdmin', function (accounts) {
it('fails to upgrade', async function () {
const callData = '0x12345678';
await expectRevert.unspecified(
this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData,
{ from: proxyAdminOwner },
),
this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
from: proxyAdminOwner,
}),
);
});
});
@ -115,9 +115,9 @@ contract('ProxyAdmin', function (accounts) {
context('with valid callData', function () {
it('upgrades implementation', async function () {
const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
await this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData,
{ from: proxyAdminOwner },
);
await this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
from: proxyAdminOwner,
});
const implementationAddress = await this.proxyAdmin.getProxyImplementation(this.proxy.address);
expect(implementationAddress).to.be.equal(this.implementationV2.address);
});

View File

@ -3,8 +3,8 @@ const { ZERO_ADDRESS } = constants;
const { getSlot, ImplementationSlot, AdminSlot } = require('../../helpers/erc1967');
const { expect } = require('chai');
const { web3 } = require('hardhat');
const Proxy = artifacts.require('Proxy');
const Implementation1 = artifacts.require('Implementation1');
const Implementation2 = artifacts.require('Implementation2');
const Implementation3 = artifacts.require('Implementation3');
@ -16,7 +16,7 @@ const InitializableMock = artifacts.require('InitializableMock');
const DummyImplementation = artifacts.require('DummyImplementation');
const ClashingImplementation = artifacts.require('ClashingImplementation');
module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createProxy, accounts) {
module.exports = function shouldBehaveLikeTransparentUpgradeableProxy(createProxy, accounts) {
const [proxyAdminAddress, proxyAdminOwner, anotherAccount] = accounts;
before(async function () {
@ -60,12 +60,9 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
});
it('emits an event', async function () {
expectEvent(
await this.proxy.upgradeTo(this.implementationV1, { from }),
'Upgraded', {
implementation: this.implementationV1,
},
);
expectEvent(await this.proxy.upgradeTo(this.implementationV1, { from }), 'Upgraded', {
implementation: this.implementationV1,
});
});
});
@ -83,9 +80,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
const from = anotherAccount;
it('reverts', async function () {
await expectRevert.unspecified(
this.proxy.upgradeTo(this.implementationV1, { from }),
);
await expectRevert.unspecified(this.proxy.upgradeTo(this.implementationV1, { from }));
});
});
});
@ -127,13 +122,11 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
expect(balance.toString()).to.be.bignumber.equal(value.toString());
});
it.skip('uses the storage of the proxy', async function () {
it('uses the storage of the proxy', async function () {
// storage layout should look as follows:
// - 0: Initializable storage
// - 1-50: Initailizable reserved storage (50 slots)
// - 51: initializerRan
// - 52: x
const storedValue = await Proxy.at(this.proxyAddress).getStorageAt(52);
// - 0: Initializable storage ++ initializerRan ++ onlyInitializingRan
// - 1: x
const storedValue = await web3.eth.getStorageAt(this.proxyAddress, 1);
expect(parseInt(storedValue)).to.eq(42);
});
});
@ -178,7 +171,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
expectEvent(this.receipt, 'Upgraded', { implementation: this.behaviorV1.address });
});
it('calls the \'initialize\' function and sends given value to the proxy', async function () {
it("calls the 'initialize' function and sends given value to the proxy", async function () {
const migratable = new MigratableMockV1(this.proxyAddress);
const x = await migratable.x();
@ -194,8 +187,10 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
beforeEach(async function () {
this.behaviorV2 = await MigratableMockV2.new();
this.balancePreviousV2 = new BN(await web3.eth.getBalance(this.proxyAddress));
this.receipt =
await this.proxy.upgradeToAndCall(this.behaviorV2.address, v2MigrationData, { from, value });
this.receipt = await this.proxy.upgradeToAndCall(this.behaviorV2.address, v2MigrationData, {
from,
value,
});
});
it('upgrades to the requested version and emits an event', async function () {
@ -204,7 +199,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
expectEvent(this.receipt, 'Upgraded', { implementation: this.behaviorV2.address });
});
it('calls the \'migrate\' function and sends given value to the proxy', async function () {
it("calls the 'migrate' function and sends given value to the proxy", async function () {
const migratable = new MigratableMockV2(this.proxyAddress);
const x = await migratable.x();
@ -223,8 +218,10 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
beforeEach(async function () {
this.behaviorV3 = await MigratableMockV3.new();
this.balancePreviousV3 = new BN(await web3.eth.getBalance(this.proxyAddress));
this.receipt =
await this.proxy.upgradeToAndCall(this.behaviorV3.address, v3MigrationData, { from, value });
this.receipt = await this.proxy.upgradeToAndCall(this.behaviorV3.address, v3MigrationData, {
from,
value,
});
});
it('upgrades to the requested version and emits an event', async function () {
@ -233,7 +230,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
expectEvent(this.receipt, 'Upgraded', { implementation: this.behaviorV3.address });
});
it('calls the \'migrate\' function and sends given value to the proxy', async function () {
it("calls the 'migrate' function and sends given value to the proxy", async function () {
const migratable = new MigratableMockV3(this.proxyAddress);
const x = await migratable.x();
@ -256,9 +253,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
it('reverts', async function () {
const behaviorV1 = await MigratableMockV1.new();
const v1MigrationData = new MigratableMockV1('').contract.methods.initialize(42).encodeABI();
await expectRevert.unspecified(
this.proxy.upgradeToAndCall(behaviorV1.address, v1MigrationData, { from }),
);
await expectRevert.unspecified(this.proxy.upgradeToAndCall(behaviorV1.address, v1MigrationData, { from }));
});
});
});
@ -428,9 +423,7 @@ module.exports = function shouldBehaveLikeTransparentUpgradeableProxy (createPro
await proxy.upgradeTo(instance2.address, { from: proxyAdminAddress });
const data = '0x';
await expectRevert.unspecified(
web3.eth.sendTransaction({ to: proxy.address, from: anotherAccount, data }),
);
await expectRevert.unspecified(web3.eth.sendTransaction({ to: proxy.address, from: anotherAccount, data }));
const proxyInstance2 = new Implementation2(proxy.address);
const res = await proxyInstance2.getValue();

View File

@ -10,7 +10,7 @@ const DisableBad1 = artifacts.require('DisableBad1');
const DisableBad2 = artifacts.require('DisableBad2');
const DisableOk = artifacts.require('DisableOk');
contract('Initializable', function (accounts) {
contract('Initializable', function () {
describe('basic testing without inheritance', function () {
beforeEach('deploying', async function () {
this.contract = await InitializableMock.new();

View File

@ -6,14 +6,14 @@ const ERC1967Proxy = artifacts.require('ERC1967Proxy');
const UUPSUpgradeableMock = artifacts.require('UUPSUpgradeableMock');
const UUPSUpgradeableUnsafeMock = artifacts.require('UUPSUpgradeableUnsafeMock');
const UUPSUpgradeableLegacyMock = artifacts.require('UUPSUpgradeableLegacyMock');
const CountersImpl = artifacts.require('CountersImpl');
const NonUpgradeableMock = artifacts.require('NonUpgradeableMock');
contract('UUPSUpgradeable', function (accounts) {
contract('UUPSUpgradeable', function () {
before(async function () {
this.implInitial = await UUPSUpgradeableMock.new();
this.implUpgradeOk = await UUPSUpgradeableMock.new();
this.implUpgradeUnsafe = await UUPSUpgradeableUnsafeMock.new();
this.implUpgradeNonUUPS = await CountersImpl.new();
this.implUpgradeNonUUPS = await NonUpgradeableMock.new();
});
beforeEach(async function () {
@ -65,14 +65,14 @@ contract('UUPSUpgradeable', function (accounts) {
it('can upgrade from legacy implementations', async function () {
const legacyImpl = await UUPSUpgradeableLegacyMock.new();
const legacyInstance = await ERC1967Proxy.new(legacyImpl.address, '0x')
.then(({ address }) => UUPSUpgradeableLegacyMock.at(address));
const legacyInstance = await ERC1967Proxy.new(legacyImpl.address, '0x').then(({ address }) =>
UUPSUpgradeableLegacyMock.at(address),
);
const receipt = await legacyInstance.upgradeTo(this.implInitial.address);
const UpgradedEvents = receipt.logs.filter(({ address, event }) =>
address === legacyInstance.address &&
event === 'Upgraded',
const UpgradedEvents = receipt.logs.filter(
({ address, event }) => address === legacyInstance.address && event === 'Upgraded',
);
expect(UpgradedEvents.length).to.be.equal(1);