ProxyAdmin.test.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. 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. const proxy = await TransparentUpgradeableProxy.new(
  18. this.implementationV1.address,
  19. this.proxyAdmin.address,
  20. initializeData,
  21. { from: proxyAdminOwner },
  22. );
  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. describe('#getProxyAdmin', function () {
  29. it('returns proxyAdmin as admin of the proxy', async function () {
  30. const admin = await this.proxyAdmin.getProxyAdmin(this.proxy.address);
  31. expect(admin).to.be.equal(this.proxyAdmin.address);
  32. });
  33. it('call to invalid proxy', async function () {
  34. await expectRevert.unspecified(this.proxyAdmin.getProxyAdmin(this.implementationV1.address));
  35. });
  36. });
  37. describe('#changeProxyAdmin', function () {
  38. it('fails to change proxy admin if its not the proxy owner', async function () {
  39. await expectRevert(
  40. this.proxyAdmin.changeProxyAdmin(this.proxy.address, newAdmin, { from: anotherAccount }),
  41. 'caller is not the owner',
  42. );
  43. });
  44. it('changes proxy admin', async function () {
  45. await this.proxyAdmin.changeProxyAdmin(this.proxy.address, newAdmin, { from: proxyAdminOwner });
  46. expect(await this.proxy.admin.call({ from: newAdmin })).to.eq(newAdmin);
  47. });
  48. });
  49. describe('#getProxyImplementation', function () {
  50. it('returns proxy implementation address', async function () {
  51. const implementationAddress = await this.proxyAdmin.getProxyImplementation(this.proxy.address);
  52. expect(implementationAddress).to.be.equal(this.implementationV1.address);
  53. });
  54. it('call to invalid proxy', async function () {
  55. await expectRevert.unspecified(this.proxyAdmin.getProxyImplementation(this.implementationV1.address));
  56. });
  57. });
  58. describe('#upgrade', function () {
  59. context('with unauthorized account', function () {
  60. it('fails to upgrade', async function () {
  61. await expectRevert(
  62. this.proxyAdmin.upgrade(this.proxy.address, this.implementationV2.address, { from: anotherAccount }),
  63. 'caller is not the owner',
  64. );
  65. });
  66. });
  67. context('with authorized account', function () {
  68. it('upgrades implementation', async function () {
  69. await this.proxyAdmin.upgrade(this.proxy.address, this.implementationV2.address, { from: proxyAdminOwner });
  70. const implementationAddress = await this.proxyAdmin.getProxyImplementation(this.proxy.address);
  71. expect(implementationAddress).to.be.equal(this.implementationV2.address);
  72. });
  73. });
  74. });
  75. describe('#upgradeAndCall', function () {
  76. context('with unauthorized account', function () {
  77. it('fails to upgrade', async function () {
  78. const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
  79. await expectRevert(
  80. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  81. from: anotherAccount,
  82. }),
  83. 'caller is not the owner',
  84. );
  85. });
  86. });
  87. context('with authorized account', function () {
  88. context('with invalid callData', function () {
  89. it('fails to upgrade', async function () {
  90. const callData = '0x12345678';
  91. await expectRevert.unspecified(
  92. this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  93. from: proxyAdminOwner,
  94. }),
  95. );
  96. });
  97. });
  98. context('with valid callData', function () {
  99. it('upgrades implementation', async function () {
  100. const callData = new ImplV1('').contract.methods.initializeNonPayableWithValue(1337).encodeABI();
  101. await this.proxyAdmin.upgradeAndCall(this.proxy.address, this.implementationV2.address, callData, {
  102. from: proxyAdminOwner,
  103. });
  104. const implementationAddress = await this.proxyAdmin.getProxyImplementation(this.proxy.address);
  105. expect(implementationAddress).to.be.equal(this.implementationV2.address);
  106. });
  107. });
  108. });
  109. });
  110. });