ProxyAdmin.test.js 4.0 KB

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