ProxyAdmin.test.js 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. contract('ProxyAdmin', function (accounts) {
  11. const [proxyAdminOwner, anotherAccount] = accounts;
  12. before('set implementations', async function () {
  13. this.implementationV1 = await ImplV1.new();
  14. this.implementationV2 = await ImplV2.new();
  15. });
  16. beforeEach(async function () {
  17. const initializeData = Buffer.from('');
  18. this.proxyAdmin = await ProxyAdmin.new(proxyAdminOwner);
  19. const proxy = await TransparentUpgradeableProxy.new(
  20. this.implementationV1.address,
  21. this.proxyAdmin.address,
  22. initializeData,
  23. );
  24. this.proxy = await ITransparentUpgradeableProxy.at(proxy.address);
  25. });
  26. it('has an owner', async function () {
  27. expect(await this.proxyAdmin.owner()).to.equal(proxyAdminOwner);
  28. });
  29. describe('#upgrade', function () {
  30. context('with unauthorized account', function () {
  31. it('fails to upgrade', async function () {
  32. await expectRevertCustomError(
  33. this.proxyAdmin.upgrade(this.proxy.address, this.implementationV2.address, { from: anotherAccount }),
  34. 'OwnableUnauthorizedAccount',
  35. [anotherAccount],
  36. );
  37. });
  38. });
  39. context('with authorized account', function () {
  40. it('upgrades implementation', async function () {
  41. await this.proxyAdmin.upgrade(this.proxy.address, this.implementationV2.address, { from: proxyAdminOwner });
  42. const implementationAddress = await getAddressInSlot(this.proxy, ImplementationSlot);
  43. expect(implementationAddress).to.be.equal(this.implementationV2.address);
  44. });
  45. });
  46. });
  47. describe('#upgradeAndCall', function () {
  48. context('with unauthorized account', function () {
  49. it('fails to upgrade', async function () {
  50. const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
  51. await expectRevertCustomError(
  52. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  53. from: anotherAccount,
  54. }),
  55. 'OwnableUnauthorizedAccount',
  56. [anotherAccount],
  57. );
  58. });
  59. });
  60. context('with authorized account', function () {
  61. context('with invalid callData', function () {
  62. it('fails to upgrade', async function () {
  63. const callData = '0x12345678';
  64. await expectRevert.unspecified(
  65. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  66. from: proxyAdminOwner,
  67. }),
  68. );
  69. });
  70. });
  71. context('with valid callData', function () {
  72. it('upgrades implementation', async function () {
  73. const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
  74. await this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  75. from: proxyAdminOwner,
  76. });
  77. const implementationAddress = await getAddressInSlot(this.proxy, ImplementationSlot);
  78. expect(implementationAddress).to.be.equal(this.implementationV2.address);
  79. });
  80. });
  81. });
  82. });
  83. });