@@ -4,12 +4,19 @@ const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
4
4
const { PANIC_CODES } = require ( '@nomicfoundation/hardhat-chai-matchers/panic' ) ;
5
5
6
6
const { Rounding } = require ( '../../helpers/enums' ) ;
7
- const { min, max } = require ( '../../helpers/math' ) ;
7
+ const { min, max, modExp } = require ( '../../helpers/math' ) ;
8
8
const { generators } = require ( '../../helpers/random' ) ;
9
+ const { range } = require ( '../../../scripts/helpers' ) ;
10
+ const { product } = require ( '../../helpers/iterate' ) ;
9
11
10
12
const RoundingDown = [ Rounding . Floor , Rounding . Trunc ] ;
11
13
const RoundingUp = [ Rounding . Ceil , Rounding . Expand ] ;
12
14
15
+ const bytes = ( value , width = undefined ) => ethers . Typed . bytes ( ethers . toBeHex ( value , width ) ) ;
16
+ const uint256 = value => ethers . Typed . uint256 ( value ) ;
17
+ bytes . zero = '0x' ;
18
+ uint256 . zero = 0n ;
19
+
13
20
async function testCommutative ( fn , lhs , rhs , expected , ...extra ) {
14
21
expect ( await fn ( lhs , rhs , ...extra ) ) . to . deep . equal ( expected ) ;
15
22
expect ( await fn ( rhs , lhs , ...extra ) ) . to . deep . equal ( expected ) ;
@@ -141,24 +148,6 @@ describe('Math', function () {
141
148
} ) ;
142
149
} ) ;
143
150
144
- describe ( 'tryModExp' , function ( ) {
145
- it ( 'is correctly returning true and calculating modulus' , async function ( ) {
146
- const base = 3n ;
147
- const exponent = 200n ;
148
- const modulus = 50n ;
149
-
150
- expect ( await this . mock . $tryModExp ( base , exponent , modulus ) ) . to . deep . equal ( [ true , base ** exponent % modulus ] ) ;
151
- } ) ;
152
-
153
- it ( 'is correctly returning false when modulus is 0' , async function ( ) {
154
- const base = 3n ;
155
- const exponent = 200n ;
156
- const modulus = 0n ;
157
-
158
- expect ( await this . mock . $tryModExp ( base , exponent , modulus ) ) . to . deep . equal ( [ false , 0n ] ) ;
159
- } ) ;
160
- } ) ;
161
-
162
151
describe ( 'max' , function ( ) {
163
152
it ( 'is correctly detected in both position' , async function ( ) {
164
153
await testCommutative ( this . mock . $max , 1234n , 5678n , max ( 1234n , 5678n ) ) ;
@@ -354,20 +343,79 @@ describe('Math', function () {
354
343
} ) ;
355
344
356
345
describe ( 'modExp' , function ( ) {
357
- it ( 'is correctly calculating modulus' , async function ( ) {
358
- const base = 3n ;
359
- const exponent = 200n ;
360
- const modulus = 50n ;
346
+ for ( const [ name , type ] of Object . entries ( { uint256, bytes } ) ) {
347
+ describe ( `with ${ name } inputs` , function ( ) {
348
+ it ( 'is correctly calculating modulus' , async function ( ) {
349
+ const b = 3n ;
350
+ const e = 200n ;
351
+ const m = 50n ;
352
+
353
+ expect ( await this . mock . $modExp ( type ( b ) , type ( e ) , type ( m ) ) ) . to . equal ( type ( b ** e % m ) . value ) ;
354
+ } ) ;
361
355
362
- expect ( await this . mock . $modExp ( base , exponent , modulus ) ) . to . equal ( base ** exponent % modulus ) ;
356
+ it ( 'is correctly reverting when modulus is zero' , async function ( ) {
357
+ const b = 3n ;
358
+ const e = 200n ;
359
+ const m = 0n ;
360
+
361
+ await expect ( this . mock . $modExp ( type ( b ) , type ( e ) , type ( m ) ) ) . to . be . revertedWithPanic (
362
+ PANIC_CODES . DIVISION_BY_ZERO ,
363
+ ) ;
364
+ } ) ;
365
+ } ) ;
366
+ }
367
+
368
+ describe ( 'with large bytes inputs' , function ( ) {
369
+ for ( const [ [ b , log2b ] , [ e , log2e ] , [ m , log2m ] ] of product (
370
+ range ( 320 , 512 , 64 ) . map ( e => [ 2n ** BigInt ( e ) + 1n , e ] ) ,
371
+ range ( 320 , 512 , 64 ) . map ( e => [ 2n ** BigInt ( e ) + 1n , e ] ) ,
372
+ range ( 320 , 512 , 64 ) . map ( e => [ 2n ** BigInt ( e ) + 1n , e ] ) ,
373
+ ) ) {
374
+ it ( `calculates b ** e % m (b=2**${ log2b } +1) (e=2**${ log2e } +1) (m=2**${ log2m } +1)` , async function ( ) {
375
+ const mLength = ethers . dataLength ( ethers . toBeHex ( m ) ) ;
376
+
377
+ expect ( await this . mock . $modExp ( bytes ( b ) , bytes ( e ) , bytes ( m ) ) ) . to . equal ( bytes ( modExp ( b , e , m ) , mLength ) . value ) ;
378
+ } ) ;
379
+ }
363
380
} ) ;
381
+ } ) ;
382
+
383
+ describe ( 'tryModExp' , function ( ) {
384
+ for ( const [ name , type ] of Object . entries ( { uint256, bytes } ) ) {
385
+ describe ( `with ${ name } inputs` , function ( ) {
386
+ it ( 'is correctly calculating modulus' , async function ( ) {
387
+ const b = 3n ;
388
+ const e = 200n ;
389
+ const m = 50n ;
390
+
391
+ expect ( await this . mock . $tryModExp ( type ( b ) , type ( e ) , type ( m ) ) ) . to . deep . equal ( [ true , type ( b ** e % m ) . value ] ) ;
392
+ } ) ;
364
393
365
- it ( 'is correctly reverting when modulus is zero' , async function ( ) {
366
- const base = 3n ;
367
- const exponent = 200n ;
368
- const modulus = 0n ;
394
+ it ( 'is correctly reverting when modulus is zero' , async function ( ) {
395
+ const b = 3n ;
396
+ const e = 200n ;
397
+ const m = 0n ;
369
398
370
- await expect ( this . mock . $modExp ( base , exponent , modulus ) ) . to . be . revertedWithPanic ( PANIC_CODES . DIVISION_BY_ZERO ) ;
399
+ expect ( await this . mock . $tryModExp ( type ( b ) , type ( e ) , type ( m ) ) ) . to . deep . equal ( [ false , type . zero ] ) ;
400
+ } ) ;
401
+ } ) ;
402
+ }
403
+
404
+ describe ( 'with large bytes inputs' , function ( ) {
405
+ for ( const [ [ b , log2b ] , [ e , log2e ] , [ m , log2m ] ] of product (
406
+ range ( 320 , 513 , 64 ) . map ( e => [ 2n ** BigInt ( e ) + 1n , e ] ) ,
407
+ range ( 320 , 513 , 64 ) . map ( e => [ 2n ** BigInt ( e ) + 1n , e ] ) ,
408
+ range ( 320 , 513 , 64 ) . map ( e => [ 2n ** BigInt ( e ) + 1n , e ] ) ,
409
+ ) ) {
410
+ it ( `calculates b ** e % m (b=2**${ log2b } +1) (e=2**${ log2e } +1) (m=2**${ log2m } +1)` , async function ( ) {
411
+ const mLength = ethers . dataLength ( ethers . toBeHex ( m ) ) ;
412
+
413
+ expect ( await this . mock . $tryModExp ( bytes ( b ) , bytes ( e ) , bytes ( m ) ) ) . to . deep . equal ( [
414
+ true ,
415
+ bytes ( modExp ( b , e , m ) , mLength ) . value ,
416
+ ] ) ;
417
+ } ) ;
418
+ }
371
419
} ) ;
372
420
} ) ;
373
421
0 commit comments