SignatureBouncer.test.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. const { assertRevert } = require('../helpers/assertRevert');
  2. const { getBouncerSigner } = require('../helpers/sign');
  3. const Bouncer = artifacts.require('SignatureBouncerMock');
  4. require('chai')
  5. .should();
  6. const UINT_VALUE = 23;
  7. const BYTES_VALUE = web3.toHex('test');
  8. const INVALID_SIGNATURE = '0xabcd';
  9. contract('Bouncer', ([_, owner, anyone, bouncerAddress, authorizedUser]) => {
  10. beforeEach(async function () {
  11. this.bouncer = await Bouncer.new({ from: owner });
  12. this.roleBouncer = await this.bouncer.ROLE_BOUNCER();
  13. });
  14. context('management', () => {
  15. it('has a default owner of self', async function () {
  16. (await this.bouncer.owner()).should.eq(owner);
  17. });
  18. it('allows the owner to add a bouncer', async function () {
  19. await this.bouncer.addBouncer(bouncerAddress, { from: owner });
  20. (await this.bouncer.hasRole(bouncerAddress, this.roleBouncer)).should.eq(true);
  21. });
  22. it('does not allow adding an invalid address', async function () {
  23. await assertRevert(
  24. this.bouncer.addBouncer('0x0', { from: owner })
  25. );
  26. });
  27. it('allows the owner to remove a bouncer', async function () {
  28. await this.bouncer.addBouncer(bouncerAddress, { from: owner });
  29. await this.bouncer.removeBouncer(bouncerAddress, { from: owner });
  30. (await this.bouncer.hasRole(bouncerAddress, this.roleBouncer)).should.eq(false);
  31. });
  32. it('does not allow anyone to add a bouncer', async function () {
  33. await assertRevert(
  34. this.bouncer.addBouncer(bouncerAddress, { from: anyone })
  35. );
  36. });
  37. it('does not allow anyone to remove a bouncer', async function () {
  38. await this.bouncer.addBouncer(bouncerAddress, { from: owner });
  39. await assertRevert(
  40. this.bouncer.removeBouncer(bouncerAddress, { from: anyone })
  41. );
  42. });
  43. });
  44. context('with bouncer address', () => {
  45. beforeEach(async function () {
  46. await this.bouncer.addBouncer(bouncerAddress, { from: owner });
  47. this.signFor = getBouncerSigner(this.bouncer, bouncerAddress);
  48. });
  49. describe('modifiers', () => {
  50. context('plain signature', () => {
  51. it('allows valid signature for sender', async function () {
  52. await this.bouncer.onlyWithValidSignature(this.signFor(authorizedUser), { from: authorizedUser });
  53. });
  54. it('does not allow invalid signature for sender', async function () {
  55. await assertRevert(
  56. this.bouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser })
  57. );
  58. });
  59. it('does not allow valid signature for other sender', async function () {
  60. await assertRevert(
  61. this.bouncer.onlyWithValidSignature(this.signFor(authorizedUser), { from: anyone })
  62. );
  63. });
  64. it('does not allow valid signature for method for sender', async function () {
  65. await assertRevert(
  66. this.bouncer.onlyWithValidSignature(this.signFor(authorizedUser, 'onlyWithValidSignature'),
  67. { from: authorizedUser })
  68. );
  69. });
  70. });
  71. context('method signature', () => {
  72. it('allows valid signature with correct method for sender', async function () {
  73. await this.bouncer.onlyWithValidSignatureAndMethod(
  74. this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: authorizedUser }
  75. );
  76. });
  77. it('does not allow invalid signature with correct method for sender', async function () {
  78. await assertRevert(
  79. this.bouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser })
  80. );
  81. });
  82. it('does not allow valid signature with correct method for other sender', async function () {
  83. await assertRevert(
  84. this.bouncer.onlyWithValidSignatureAndMethod(
  85. this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: anyone }
  86. )
  87. );
  88. });
  89. it('does not allow valid method signature with incorrect method for sender', async function () {
  90. await assertRevert(
  91. this.bouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser, 'theWrongMethod'),
  92. { from: authorizedUser })
  93. );
  94. });
  95. it('does not allow valid non-method signature method for sender', async function () {
  96. await assertRevert(
  97. this.bouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser), { from: authorizedUser })
  98. );
  99. });
  100. });
  101. context('method and data signature', () => {
  102. it('allows valid signature with correct method and data for sender', async function () {
  103. await this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE,
  104. this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: authorizedUser }
  105. );
  106. });
  107. it('does not allow invalid signature with correct method and data for sender', async function () {
  108. await assertRevert(
  109. this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser })
  110. );
  111. });
  112. it('does not allow valid signature with correct method and incorrect data for sender', async function () {
  113. await assertRevert(
  114. this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10,
  115. this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
  116. { from: authorizedUser }
  117. )
  118. );
  119. });
  120. it('does not allow valid signature with correct method and data for other sender', async function () {
  121. await assertRevert(
  122. this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE,
  123. this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
  124. { from: anyone }
  125. )
  126. );
  127. });
  128. it('does not allow valid non-method signature for sender', async function () {
  129. await assertRevert(
  130. this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE,
  131. this.signFor(authorizedUser), { from: authorizedUser }
  132. )
  133. );
  134. });
  135. });
  136. });
  137. context('signature validation', () => {
  138. context('plain signature', () => {
  139. it('validates valid signature for valid user', async function () {
  140. (await this.bouncer.checkValidSignature(authorizedUser, this.signFor(authorizedUser))).should.eq(true);
  141. });
  142. it('does not validate invalid signature for valid user', async function () {
  143. (await this.bouncer.checkValidSignature(authorizedUser, INVALID_SIGNATURE)).should.eq(false);
  144. });
  145. it('does not validate valid signature for anyone', async function () {
  146. (await this.bouncer.checkValidSignature(anyone, this.signFor(authorizedUser))).should.eq(false);
  147. });
  148. it('does not validate valid signature for method for valid user', async function () {
  149. (await this.bouncer.checkValidSignature(authorizedUser, this.signFor(authorizedUser, 'checkValidSignature'))
  150. ).should.eq(false);
  151. });
  152. });
  153. context('method signature', () => {
  154. it('validates valid signature with correct method for valid user', async function () {
  155. (await this.bouncer.checkValidSignatureAndMethod(authorizedUser,
  156. this.signFor(authorizedUser, 'checkValidSignatureAndMethod'))
  157. ).should.eq(true);
  158. });
  159. it('does not validate invalid signature with correct method for valid user', async function () {
  160. (await this.bouncer.checkValidSignatureAndMethod(authorizedUser, INVALID_SIGNATURE)).should.eq(false);
  161. });
  162. it('does not validate valid signature with correct method for anyone', async function () {
  163. (await this.bouncer.checkValidSignatureAndMethod(anyone,
  164. this.signFor(authorizedUser, 'checkValidSignatureAndMethod'))
  165. ).should.eq(false);
  166. });
  167. it('does not validate valid non-method signature with correct method for valid user', async function () {
  168. (await this.bouncer.checkValidSignatureAndMethod(authorizedUser, this.signFor(authorizedUser))
  169. ).should.eq(false);
  170. });
  171. });
  172. context('method and data signature', () => {
  173. it('validates valid signature with correct method and data for valid user', async function () {
  174. (await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE,
  175. this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
  176. ).should.eq(true);
  177. });
  178. it('does not validate invalid signature with correct method and data for valid user', async function () {
  179. (await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE, INVALID_SIGNATURE)
  180. ).should.eq(false);
  181. });
  182. it('does not validate valid signature with correct method and incorrect data for valid user',
  183. async function () {
  184. (await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE + 10,
  185. this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
  186. ).should.eq(false);
  187. }
  188. );
  189. it('does not validate valid signature with correct method and data for anyone', async function () {
  190. (await this.bouncer.checkValidSignatureAndData(anyone, BYTES_VALUE, UINT_VALUE,
  191. this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
  192. ).should.eq(false);
  193. });
  194. it('does not validate valid non-method-data signature with correct method and data for valid user',
  195. async function () {
  196. (await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE,
  197. this.signFor(authorizedUser, 'checkValidSignatureAndData'))
  198. ).should.eq(false);
  199. }
  200. );
  201. });
  202. });
  203. });
  204. });