SignatureBouncer.test.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. const { shouldFail } = require('openzeppelin-test-helpers');
  2. const { getSignFor } = require('../helpers/sign');
  3. const { shouldBehaveLikePublicRole } = require('../behaviors/access/roles/PublicRole.behavior');
  4. const SignatureBouncerMock = artifacts.require('SignatureBouncerMock');
  5. const UINT_VALUE = 23;
  6. const BYTES_VALUE = web3.utils.toHex('test');
  7. const INVALID_SIGNATURE = '0xabcd';
  8. contract('SignatureBouncer', function ([_, signer, otherSigner, other, authorizedUser, ...otherAccounts]) {
  9. beforeEach(async function () {
  10. this.sigBouncer = await SignatureBouncerMock.new({ from: signer });
  11. this.signFor = getSignFor(this.sigBouncer, signer);
  12. });
  13. describe('signer role', function () {
  14. beforeEach(async function () {
  15. this.contract = this.sigBouncer;
  16. await this.contract.addSigner(otherSigner, { from: signer });
  17. });
  18. shouldBehaveLikePublicRole(signer, otherSigner, otherAccounts, 'signer');
  19. });
  20. describe('modifiers', function () {
  21. context('plain signature', function () {
  22. it('allows valid signature for sender', async function () {
  23. await this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser), { from: authorizedUser });
  24. });
  25. it('does not allow invalid signature for sender', async function () {
  26. await shouldFail.reverting.withMessage(
  27. this.sigBouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser }),
  28. 'SignatureBouncer: invalid signature for caller'
  29. );
  30. });
  31. it('does not allow valid signature for other sender', async function () {
  32. await shouldFail.reverting.withMessage(
  33. this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser), { from: other }),
  34. 'SignatureBouncer: invalid signature for caller'
  35. );
  36. });
  37. it('does not allow valid signature for method for sender', async function () {
  38. await shouldFail.reverting.withMessage(
  39. this.sigBouncer.onlyWithValidSignature(await this.signFor(authorizedUser, 'onlyWithValidSignature'),
  40. { from: authorizedUser }), 'SignatureBouncer: invalid signature for caller'
  41. );
  42. });
  43. });
  44. context('method signature', function () {
  45. it('allows valid signature with correct method for sender', async function () {
  46. await this.sigBouncer.onlyWithValidSignatureAndMethod(
  47. await this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: authorizedUser }
  48. );
  49. });
  50. it('does not allow invalid signature with correct method for sender', async function () {
  51. await shouldFail.reverting.withMessage(
  52. this.sigBouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser }),
  53. 'SignatureBouncer: invalid signature for caller and method'
  54. );
  55. });
  56. it('does not allow valid signature with correct method for other sender', async function () {
  57. await shouldFail.reverting.withMessage(
  58. this.sigBouncer.onlyWithValidSignatureAndMethod(
  59. await this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: other }
  60. ),
  61. 'SignatureBouncer: invalid signature for caller and method'
  62. );
  63. });
  64. it('does not allow valid method signature with incorrect method for sender', async function () {
  65. await shouldFail.reverting.withMessage(
  66. this.sigBouncer.onlyWithValidSignatureAndMethod(await this.signFor(authorizedUser, 'theWrongMethod'),
  67. { from: authorizedUser }), 'SignatureBouncer: invalid signature for caller and method'
  68. );
  69. });
  70. it('does not allow valid non-method signature method for sender', async function () {
  71. await shouldFail.reverting.withMessage(
  72. this.sigBouncer.onlyWithValidSignatureAndMethod(await this.signFor(authorizedUser), { from: authorizedUser }),
  73. 'SignatureBouncer: invalid signature for caller and method'
  74. );
  75. });
  76. });
  77. context('method and data signature', function () {
  78. it('allows valid signature with correct method and data for sender', async function () {
  79. await this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE,
  80. await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: authorizedUser }
  81. );
  82. });
  83. it('does not allow invalid signature with correct method and data for sender', async function () {
  84. await shouldFail.reverting.withMessage(
  85. this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser }),
  86. 'SignatureBouncer: invalid signature for caller and data'
  87. );
  88. });
  89. it('does not allow valid signature with correct method and incorrect data for sender', async function () {
  90. await shouldFail.reverting.withMessage(
  91. this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10,
  92. await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
  93. { from: authorizedUser }
  94. ), 'SignatureBouncer: invalid signature for caller and data'
  95. );
  96. });
  97. it('does not allow valid signature with correct method and data for other sender', async function () {
  98. await shouldFail.reverting.withMessage(
  99. this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE,
  100. await this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
  101. { from: other }
  102. ), 'SignatureBouncer: invalid signature for caller and data'
  103. );
  104. });
  105. it('does not allow valid non-method signature for sender', async function () {
  106. await shouldFail.reverting.withMessage(
  107. this.sigBouncer.onlyWithValidSignatureAndData(UINT_VALUE,
  108. await this.signFor(authorizedUser), { from: authorizedUser }
  109. ), 'SignatureBouncer: invalid signature for caller and data'
  110. );
  111. });
  112. it('does not allow msg.data shorter than SIGNATURE_SIZE', async function () {
  113. await shouldFail.reverting.withMessage(
  114. this.sigBouncer.tooShortMsgData({ from: authorizedUser }), 'SignatureBouncer: data is too short'
  115. );
  116. });
  117. });
  118. });
  119. context('signature validation', function () {
  120. context('plain signature', function () {
  121. it('validates valid signature for valid user', async function () {
  122. (await this.sigBouncer.checkValidSignature(authorizedUser, await this.signFor(authorizedUser)))
  123. .should.equal(true);
  124. });
  125. it('does not validate invalid signature for valid user', async function () {
  126. (await this.sigBouncer.checkValidSignature(authorizedUser, INVALID_SIGNATURE)).should.equal(false);
  127. });
  128. it('does not validate valid signature for anyone', async function () {
  129. (await this.sigBouncer.checkValidSignature(other, await this.signFor(authorizedUser))).should.equal(false);
  130. });
  131. it('does not validate valid signature for method for valid user', async function () {
  132. (await this.sigBouncer.checkValidSignature(
  133. authorizedUser, await this.signFor(authorizedUser, 'checkValidSignature'))
  134. ).should.equal(false);
  135. });
  136. });
  137. context('method signature', function () {
  138. it('validates valid signature with correct method for valid user', async function () {
  139. (await this.sigBouncer.checkValidSignatureAndMethod(authorizedUser,
  140. await this.signFor(authorizedUser, 'checkValidSignatureAndMethod'))
  141. ).should.equal(true);
  142. });
  143. it('does not validate invalid signature with correct method for valid user', async function () {
  144. (await this.sigBouncer.checkValidSignatureAndMethod(authorizedUser, INVALID_SIGNATURE)).should.equal(false);
  145. });
  146. it('does not validate valid signature with correct method for anyone', async function () {
  147. (await this.sigBouncer.checkValidSignatureAndMethod(other,
  148. await this.signFor(authorizedUser, 'checkValidSignatureAndMethod'))
  149. ).should.equal(false);
  150. });
  151. it('does not validate valid non-method signature with correct method for valid user', async function () {
  152. (await this.sigBouncer.checkValidSignatureAndMethod(authorizedUser, await this.signFor(authorizedUser))
  153. ).should.equal(false);
  154. });
  155. });
  156. context('method and data signature', function () {
  157. it('validates valid signature with correct method and data for valid user', async function () {
  158. (await this.sigBouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE,
  159. await this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
  160. ).should.equal(true);
  161. });
  162. it('does not validate invalid signature with correct method and data for valid user', async function () {
  163. (await this.sigBouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE, INVALID_SIGNATURE)
  164. ).should.equal(false);
  165. });
  166. it('does not validate valid signature with correct method and incorrect data for valid user',
  167. async function () {
  168. (await this.sigBouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE + 10,
  169. await this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
  170. ).should.equal(false);
  171. }
  172. );
  173. it('does not validate valid signature with correct method and data for anyone', async function () {
  174. (await this.sigBouncer.checkValidSignatureAndData(other, BYTES_VALUE, UINT_VALUE,
  175. await this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
  176. ).should.equal(false);
  177. });
  178. it('does not validate valid non-method-data signature with correct method and data for valid user',
  179. async function () {
  180. (await this.sigBouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE,
  181. await this.signFor(authorizedUser, 'checkValidSignatureAndData'))
  182. ).should.equal(false);
  183. }
  184. );
  185. });
  186. });
  187. });