ProxyAdmin.test.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. const { expectRevert } = require('@openzeppelin/test-helpers');
  2. const { expect } = require('chai');
  3. const ImplV1 = artifacts.require('DummyImplementation');
  4. const ImplV2 = artifacts.require('DummyImplementationV2');
  5. const ProxyAdmin = artifacts.require('ProxyAdmin');
  6. const TransparentUpgradeableProxy = artifacts.require('TransparentUpgradeableProxy');
  7. const ITransparentUpgradeableProxy = artifacts.require('ITransparentUpgradeableProxy');
  8. const { getAddressInSlot, ImplementationSlot } = require('../../helpers/erc1967');
  9. const { expectRevertCustomError } = require('../../helpers/customError');
  10. const { computeCreateAddress } = require('../../helpers/create');
  11. contract('ProxyAdmin', function (accounts) {
  12. const [proxyAdminOwner, anotherAccount] = accounts;
  13. before('set implementations', async function () {
  14. this.implementationV1 = await ImplV1.new();
  15. this.implementationV2 = await ImplV2.new();
  16. });
  17. beforeEach(async function () {
  18. const initializeData = Buffer.from('');
  19. const proxy = await TransparentUpgradeableProxy.new(this.implementationV1.address, proxyAdminOwner, initializeData);
  20. const proxyNonce = await web3.eth.getTransactionCount(proxy.address);
  21. const proxyAdminAddress = computeCreateAddress(proxy.address, proxyNonce - 1); // Nonce already used
  22. this.proxyAdmin = await ProxyAdmin.at(proxyAdminAddress);
  23. this.proxy = await ITransparentUpgradeableProxy.at(proxy.address);
  24. });
  25. it('has an owner', async function () {
  26. expect(await this.proxyAdmin.owner()).to.equal(proxyAdminOwner);
  27. });
  28. it('has an interface version', async function () {
  29. expect(await this.proxyAdmin.UPGRADE_INTERFACE_VERSION()).to.equal('5.0.0');
  30. });
  31. describe('without data', function () {
  32. context('with unauthorized account', function () {
  33. it('fails to upgrade', async function () {
  34. await expectRevertCustomError(
  35. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, '0x', {
  36. from: anotherAccount,
  37. }),
  38. 'OwnableUnauthorizedAccount',
  39. [anotherAccount],
  40. );
  41. });
  42. });
  43. context('with authorized account', function () {
  44. it('upgrades implementation', async function () {
  45. await this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, '0x', {
  46. from: proxyAdminOwner,
  47. });
  48. const implementationAddress = await getAddressInSlot(this.proxy, ImplementationSlot);
  49. expect(implementationAddress).to.be.equal(this.implementationV2.address);
  50. });
  51. });
  52. });
  53. describe('with data', function () {
  54. context('with unauthorized account', function () {
  55. it('fails to upgrade', async function () {
  56. const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
  57. await expectRevertCustomError(
  58. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  59. from: anotherAccount,
  60. }),
  61. 'OwnableUnauthorizedAccount',
  62. [anotherAccount],
  63. );
  64. });
  65. });
  66. context('with authorized account', function () {
  67. context('with invalid callData', function () {
  68. it('fails to upgrade', async function () {
  69. const callData = '0x12345678';
  70. await expectRevert.unspecified(
  71. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  72. from: proxyAdminOwner,
  73. }),
  74. );
  75. });
  76. });
  77. context('with valid callData', function () {
  78. it('upgrades implementation', async function () {
  79. const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
  80. await this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  81. from: proxyAdminOwner,
  82. });
  83. const implementationAddress = await getAddressInSlot(this.proxy, ImplementationSlot);
  84. expect(implementationAddress).to.be.equal(this.implementationV2.address);
  85. });
  86. });
  87. });
  88. });
  89. });