Proxy.behaviour.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. const { expectRevert } = require('@openzeppelin/test-helpers');
  2. const { getSlot, ImplementationSlot } = require('../helpers/erc1967');
  3. const { expect } = require('chai');
  4. const { expectRevertCustomError } = require('../helpers/customError');
  5. const DummyImplementation = artifacts.require('DummyImplementation');
  6. module.exports = function shouldBehaveLikeProxy(createProxy, accounts) {
  7. it('cannot be initialized with a non-contract address', async function () {
  8. const nonContractAddress = accounts[0];
  9. const initializeData = Buffer.from('');
  10. await expectRevert.unspecified(createProxy(nonContractAddress, initializeData));
  11. });
  12. before('deploy implementation', async function () {
  13. this.implementation = web3.utils.toChecksumAddress((await DummyImplementation.new()).address);
  14. });
  15. const assertProxyInitialization = function ({ value, balance }) {
  16. it('sets the implementation address', async function () {
  17. const implementationSlot = await getSlot(this.proxy, ImplementationSlot);
  18. const implementationAddress = web3.utils.toChecksumAddress(implementationSlot.substr(-40));
  19. expect(implementationAddress).to.be.equal(this.implementation);
  20. });
  21. it('initializes the proxy', async function () {
  22. const dummy = new DummyImplementation(this.proxy);
  23. expect(await dummy.value()).to.be.bignumber.equal(value.toString());
  24. });
  25. it('has expected balance', async function () {
  26. expect(await web3.eth.getBalance(this.proxy)).to.be.bignumber.equal(balance.toString());
  27. });
  28. };
  29. describe('without initialization', function () {
  30. const initializeData = Buffer.from('');
  31. describe('when not sending balance', function () {
  32. beforeEach('creating proxy', async function () {
  33. this.proxy = (await createProxy(this.implementation, initializeData)).address;
  34. });
  35. assertProxyInitialization({ value: 0, balance: 0 });
  36. });
  37. describe('when sending some balance', function () {
  38. const value = 10e5;
  39. it('reverts', async function () {
  40. await expectRevertCustomError(
  41. createProxy(this.implementation, initializeData, { value }),
  42. 'ERC1967NonPayable',
  43. [],
  44. );
  45. });
  46. });
  47. });
  48. describe('initialization without parameters', function () {
  49. describe('non payable', function () {
  50. const expectedInitializedValue = 10;
  51. const initializeData = new DummyImplementation('').contract.methods['initializeNonPayable()']().encodeABI();
  52. describe('when not sending balance', function () {
  53. beforeEach('creating proxy', async function () {
  54. this.proxy = (await createProxy(this.implementation, initializeData)).address;
  55. });
  56. assertProxyInitialization({
  57. value: expectedInitializedValue,
  58. balance: 0,
  59. });
  60. });
  61. describe('when sending some balance', function () {
  62. const value = 10e5;
  63. it('reverts', async function () {
  64. await expectRevert.unspecified(createProxy(this.implementation, initializeData, { value }));
  65. });
  66. });
  67. });
  68. describe('payable', function () {
  69. const expectedInitializedValue = 100;
  70. const initializeData = new DummyImplementation('').contract.methods['initializePayable()']().encodeABI();
  71. describe('when not sending balance', function () {
  72. beforeEach('creating proxy', async function () {
  73. this.proxy = (await createProxy(this.implementation, initializeData)).address;
  74. });
  75. assertProxyInitialization({
  76. value: expectedInitializedValue,
  77. balance: 0,
  78. });
  79. });
  80. describe('when sending some balance', function () {
  81. const value = 10e5;
  82. beforeEach('creating proxy', async function () {
  83. this.proxy = (await createProxy(this.implementation, initializeData, { value })).address;
  84. });
  85. assertProxyInitialization({
  86. value: expectedInitializedValue,
  87. balance: value,
  88. });
  89. });
  90. });
  91. });
  92. describe('initialization with parameters', function () {
  93. describe('non payable', function () {
  94. const expectedInitializedValue = 10;
  95. const initializeData = new DummyImplementation('').contract.methods
  96. .initializeNonPayableWithValue(expectedInitializedValue)
  97. .encodeABI();
  98. describe('when not sending balance', function () {
  99. beforeEach('creating proxy', async function () {
  100. this.proxy = (await createProxy(this.implementation, initializeData)).address;
  101. });
  102. assertProxyInitialization({
  103. value: expectedInitializedValue,
  104. balance: 0,
  105. });
  106. });
  107. describe('when sending some balance', function () {
  108. const value = 10e5;
  109. it('reverts', async function () {
  110. await expectRevert.unspecified(createProxy(this.implementation, initializeData, { value }));
  111. });
  112. });
  113. });
  114. describe('payable', function () {
  115. const expectedInitializedValue = 42;
  116. const initializeData = new DummyImplementation('').contract.methods
  117. .initializePayableWithValue(expectedInitializedValue)
  118. .encodeABI();
  119. describe('when not sending balance', function () {
  120. beforeEach('creating proxy', async function () {
  121. this.proxy = (await createProxy(this.implementation, initializeData)).address;
  122. });
  123. assertProxyInitialization({
  124. value: expectedInitializedValue,
  125. balance: 0,
  126. });
  127. });
  128. describe('when sending some balance', function () {
  129. const value = 10e5;
  130. beforeEach('creating proxy', async function () {
  131. this.proxy = (await createProxy(this.implementation, initializeData, { value })).address;
  132. });
  133. assertProxyInitialization({
  134. value: expectedInitializedValue,
  135. balance: value,
  136. });
  137. });
  138. });
  139. describe('reverting initialization', function () {
  140. const initializeData = new DummyImplementation('').contract.methods.reverts().encodeABI();
  141. it('reverts', async function () {
  142. await expectRevert(createProxy(this.implementation, initializeData), 'DummyImplementation reverted');
  143. });
  144. });
  145. });
  146. };