ProxyAdmin.test.js 4.8 KB

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