Clones.behaviour.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. const { ethers } = require('hardhat');
  2. const { expect } = require('chai');
  3. module.exports = function shouldBehaveLikeClone() {
  4. const assertProxyInitialization = function ({ value, balance }) {
  5. it('initializes the proxy', async function () {
  6. const dummy = await ethers.getContractAt('DummyImplementation', this.proxy);
  7. expect(await dummy.value()).to.equal(value);
  8. });
  9. it('has expected balance', async function () {
  10. expect(await ethers.provider.getBalance(this.proxy)).to.equal(balance);
  11. });
  12. };
  13. describe('construct with value', function () {
  14. const value = 10n;
  15. it('factory has enough balance', async function () {
  16. await this.deployer.sendTransaction({ to: this.factory, value });
  17. const instance = await this.createClone({ deployValue: value });
  18. await expect(instance.deploymentTransaction()).to.changeEtherBalances([this.factory, instance], [-value, value]);
  19. expect(await ethers.provider.getBalance(instance)).to.equal(value);
  20. });
  21. it('factory does not have enough balance', async function () {
  22. await expect(this.createClone({ deployValue: value }))
  23. .to.be.revertedWithCustomError(this.factory, 'InsufficientBalance')
  24. .withArgs(0n, value);
  25. });
  26. });
  27. describe('initialization without parameters', function () {
  28. describe('non payable', function () {
  29. const expectedInitializedValue = 10n;
  30. beforeEach(async function () {
  31. this.initializeData = await this.implementation.interface.encodeFunctionData('initializeNonPayable');
  32. });
  33. describe('when not sending balance', function () {
  34. beforeEach('creating proxy', async function () {
  35. this.proxy = await this.createClone({ initData: this.initializeData });
  36. });
  37. assertProxyInitialization({
  38. value: expectedInitializedValue,
  39. balance: 0,
  40. });
  41. });
  42. describe('when sending some balance', function () {
  43. const value = 10n ** 6n;
  44. it('reverts', async function () {
  45. await expect(this.createClone({ initData: this.initializeData, initValue: value })).to.be.reverted;
  46. });
  47. });
  48. });
  49. describe('payable', function () {
  50. const expectedInitializedValue = 100n;
  51. beforeEach(async function () {
  52. this.initializeData = await this.implementation.interface.encodeFunctionData('initializePayable');
  53. });
  54. describe('when not sending balance', function () {
  55. beforeEach('creating proxy', async function () {
  56. this.proxy = await this.createClone({ initData: this.initializeData });
  57. });
  58. assertProxyInitialization({
  59. value: expectedInitializedValue,
  60. balance: 0,
  61. });
  62. });
  63. describe('when sending some balance', function () {
  64. const value = 10n ** 6n;
  65. beforeEach('creating proxy', async function () {
  66. this.proxy = await this.createClone({ initData: this.initializeData, initValue: value });
  67. });
  68. assertProxyInitialization({
  69. value: expectedInitializedValue,
  70. balance: value,
  71. });
  72. });
  73. });
  74. });
  75. describe('initialization with parameters', function () {
  76. describe('non payable', function () {
  77. const expectedInitializedValue = 10n;
  78. beforeEach(async function () {
  79. this.initializeData = await this.implementation.interface.encodeFunctionData('initializeNonPayableWithValue', [
  80. expectedInitializedValue,
  81. ]);
  82. });
  83. describe('when not sending balance', function () {
  84. beforeEach('creating proxy', async function () {
  85. this.proxy = await this.createClone({ initData: this.initializeData });
  86. });
  87. assertProxyInitialization({
  88. value: expectedInitializedValue,
  89. balance: 0,
  90. });
  91. });
  92. describe('when sending some balance', function () {
  93. const value = 10n ** 6n;
  94. it('reverts', async function () {
  95. await expect(this.createClone({ initData: this.initializeData, initValue: value })).to.be.reverted;
  96. });
  97. });
  98. });
  99. describe('payable', function () {
  100. const expectedInitializedValue = 42n;
  101. beforeEach(function () {
  102. this.initializeData = this.implementation.interface.encodeFunctionData('initializePayableWithValue', [
  103. expectedInitializedValue,
  104. ]);
  105. });
  106. describe('when not sending balance', function () {
  107. beforeEach('creating proxy', async function () {
  108. this.proxy = await this.createClone({ initData: this.initializeData });
  109. });
  110. assertProxyInitialization({
  111. value: expectedInitializedValue,
  112. balance: 0,
  113. });
  114. });
  115. describe('when sending some balance', function () {
  116. const value = 10n ** 6n;
  117. beforeEach('creating proxy', async function () {
  118. this.proxy = await this.createClone({ initData: this.initializeData, initValue: value });
  119. });
  120. assertProxyInitialization({
  121. value: expectedInitializedValue,
  122. balance: value,
  123. });
  124. });
  125. });
  126. });
  127. };