@@ -37,6 +37,7 @@ module EVM.ABI
37
37
, SolError (.. )
38
38
, Anonymity (.. )
39
39
, Indexed (.. )
40
+ , Sig (.. )
40
41
, putAbi
41
42
, getAbi
42
43
, getAbiSeq
@@ -82,13 +83,17 @@ import Data.Vector (Vector, toList)
82
83
import Data.Vector qualified as Vector
83
84
import Data.Word (Word32 )
84
85
import GHC.Generics (Generic )
85
-
86
86
import Test.QuickCheck hiding ((.&.) , label )
87
+
87
88
import Text.Megaparsec qualified as P
88
89
import Text.Megaparsec.Char qualified as P
89
90
import Text.ParserCombinators.ReadP
90
91
import Witch (unsafeInto , into )
91
92
93
+ -- | A method name, and the (ordered) types of it's arguments
94
+ data Sig = Sig Text [AbiType ]
95
+ deriving (Show , Eq )
96
+
92
97
data AbiValue
93
98
= AbiUInt Int Word256
94
99
| AbiInt Int Int256
@@ -410,80 +415,6 @@ getBytesWith256BitPadding i =
410
415
<* skip ((roundTo32Bytes n) - n)
411
416
where n = fromIntegral i
412
417
413
- -- QuickCheck instances
414
-
415
- genAbiValue :: AbiType -> Gen AbiValue
416
- genAbiValue = \ case
417
- AbiUIntType n -> AbiUInt n <$> genUInt n
418
- AbiIntType n -> do
419
- x <- genUInt n
420
- pure $ AbiInt n (signedWord (x - 2 ^ (n- 1 )))
421
- AbiAddressType ->
422
- AbiAddress . fromIntegral <$> genUInt 20
423
- AbiBoolType ->
424
- elements [AbiBool False , AbiBool True ]
425
- AbiBytesType n ->
426
- do xs <- replicateM n arbitrary
427
- pure (AbiBytes n (BS. pack xs))
428
- AbiBytesDynamicType ->
429
- AbiBytesDynamic . BS. pack <$> listOf arbitrary
430
- AbiStringType ->
431
- AbiString . BS. pack <$> listOf arbitrary
432
- AbiArrayDynamicType t ->
433
- do xs <- listOf1 (scale (`div` 2 ) (genAbiValue t))
434
- pure (AbiArrayDynamic t (Vector. fromList xs))
435
- AbiArrayType n t ->
436
- AbiArray n t . Vector. fromList <$>
437
- replicateM n (scale (`div` 2 ) (genAbiValue t))
438
- AbiTupleType ts ->
439
- AbiTuple <$> mapM genAbiValue ts
440
- AbiFunctionType ->
441
- do xs <- replicateM 24 arbitrary
442
- pure (AbiFunction (BS. pack xs))
443
- where
444
- genUInt :: Int -> Gen Word256
445
- genUInt n = arbitraryIntegralWithMax (2 ^ n- 1 ) :: Gen Word256
446
-
447
- instance Arbitrary AbiType where
448
- arbitrary = oneof
449
- [ (AbiUIntType . (* 8 )) <$> choose (1 , 32 )
450
- , (AbiIntType . (* 8 )) <$> choose (1 , 32 )
451
- , pure AbiAddressType
452
- , pure AbiBoolType
453
- , AbiBytesType <$> choose (1 ,32 )
454
- , pure AbiBytesDynamicType
455
- , pure AbiStringType
456
- , AbiArrayDynamicType <$> scale (`div` 2 ) arbitrary
457
- , AbiArrayType
458
- <$> (getPositive <$> arbitrary)
459
- <*> scale (`div` 2 ) arbitrary
460
- ]
461
-
462
- instance Arbitrary AbiValue where
463
- arbitrary = arbitrary >>= genAbiValue
464
- shrink = \ case
465
- AbiArrayDynamic t v ->
466
- Vector. toList v ++
467
- map (AbiArrayDynamic t . Vector. fromList)
468
- (shrinkList shrink (Vector. toList v))
469
- AbiBytesDynamic b -> AbiBytesDynamic . BS. pack <$> shrinkList shrinkIntegral (BS. unpack b)
470
- AbiString b -> AbiString . BS. pack <$> shrinkList shrinkIntegral (BS. unpack b)
471
- AbiBytes n a | n <= 32 -> shrink $ AbiUInt (n * 8 ) (word256 a)
472
- -- bytesN for N > 32 don't really exist right now anyway..
473
- AbiBytes _ _ | otherwise -> []
474
- AbiArray _ t v ->
475
- Vector. toList v ++
476
- map (\ x -> AbiArray (length x) t (Vector. fromList x))
477
- (shrinkList shrink (Vector. toList v))
478
- AbiTuple v -> Vector. toList $ AbiTuple . Vector. fromList . shrink <$> v
479
- AbiUInt n a -> AbiUInt n <$> (shrinkIntegral a)
480
- AbiInt n a -> AbiInt n <$> (shrinkIntegral a)
481
- AbiBool b -> AbiBool <$> shrink b
482
- AbiAddress a -> [AbiAddress 0xacab , AbiAddress 0xdeadbeef , AbiAddress 0xbabeface ]
483
- <> (AbiAddress <$> shrinkIntegral a)
484
- AbiFunction b -> shrink $ AbiBytes 24 b
485
-
486
-
487
418
-- Bool synonym with custom read instance
488
419
-- to be able to parse lower case 'false' and 'true'
489
420
newtype Boolz = Boolz Bool
@@ -572,3 +503,93 @@ decodeBuf tps buf
572
503
decodeStaticArgs :: Int -> Int -> Expr Buf -> [Expr EWord ]
573
504
decodeStaticArgs offset numArgs b =
574
505
[readWord (Lit . unsafeInto $ i) b | i <- [offset,(offset+ 32 ) .. (offset + (numArgs- 1 )* 32 )]]
506
+
507
+ -- QuickCheck instances
508
+
509
+ genAbiValue :: AbiType -> Gen AbiValue
510
+ genAbiValue = \ case
511
+ AbiUIntType n -> AbiUInt n <$> genUInt n
512
+ AbiIntType n -> do
513
+ x <- genUInt n
514
+ pure $ AbiInt n (signedWord (x - 2 ^ (n- 1 )))
515
+ AbiAddressType ->
516
+ AbiAddress . fromIntegral <$> genUInt 20
517
+ AbiBoolType ->
518
+ elements [AbiBool False , AbiBool True ]
519
+ AbiBytesType n ->
520
+ do xs <- replicateM n arbitrary
521
+ pure (AbiBytes n (BS. pack xs))
522
+ AbiBytesDynamicType ->
523
+ AbiBytesDynamic . BS. pack <$> listOf arbitrary
524
+ AbiStringType ->
525
+ AbiString . BS. pack <$> listOf arbitrary
526
+ AbiArrayDynamicType t ->
527
+ do xs <- listOf1 (scale (`div` 2 ) (genAbiValue t))
528
+ pure (AbiArrayDynamic t (Vector. fromList xs))
529
+ AbiArrayType n t ->
530
+ AbiArray n t . Vector. fromList <$>
531
+ replicateM n (scale (`div` 2 ) (genAbiValue t))
532
+ AbiTupleType ts ->
533
+ AbiTuple <$> mapM genAbiValue ts
534
+ AbiFunctionType ->
535
+ do xs <- replicateM 24 arbitrary
536
+ pure (AbiFunction (BS. pack xs))
537
+ where
538
+ genUInt :: Int -> Gen Word256
539
+ genUInt n = arbitraryIntegralWithMax (2 ^ n- 1 ) :: Gen Word256
540
+
541
+ instance Arbitrary AbiType where
542
+ arbitrary = oneof
543
+ [ (AbiUIntType . (* 8 )) <$> choose (1 , 32 )
544
+ , (AbiIntType . (* 8 )) <$> choose (1 , 32 )
545
+ , pure AbiAddressType
546
+ , pure AbiBoolType
547
+ , AbiBytesType <$> choose (1 ,32 )
548
+ , pure AbiBytesDynamicType
549
+ , pure AbiStringType
550
+ , AbiArrayDynamicType <$> scale (`div` 2 ) arbitrary
551
+ , AbiArrayType
552
+ <$> (getPositive <$> arbitrary)
553
+ <*> scale (`div` 2 ) arbitrary
554
+ ]
555
+
556
+ instance Arbitrary AbiValue where
557
+ arbitrary = arbitrary >>= genAbiValue
558
+ shrink = \ case
559
+ AbiArrayDynamic t v ->
560
+ Vector. toList v ++
561
+ map (AbiArrayDynamic t . Vector. fromList)
562
+ (shrinkList shrink (Vector. toList v))
563
+ AbiBytesDynamic b -> AbiBytesDynamic . BS. pack <$> shrinkList shrinkIntegral (BS. unpack b)
564
+ AbiString b -> AbiString . BS. pack <$> shrinkList shrinkIntegral (BS. unpack b)
565
+ AbiBytes n a | n <= 32 -> shrink $ AbiUInt (n * 8 ) (word256 a)
566
+ -- bytesN for N > 32 don't really exist right now anyway..
567
+ AbiBytes _ _ | otherwise -> []
568
+ AbiArray _ t v ->
569
+ Vector. toList v ++
570
+ map (\ x -> AbiArray (length x) t (Vector. fromList x))
571
+ (shrinkList shrink (Vector. toList v))
572
+ AbiTuple v -> Vector. toList $ AbiTuple . Vector. fromList . shrink <$> v
573
+ AbiUInt n a -> AbiUInt n <$> (shrinkIntegral a)
574
+ AbiInt n a -> AbiInt n <$> (shrinkIntegral a)
575
+ AbiBool b -> AbiBool <$> shrink b
576
+ AbiAddress a -> [AbiAddress 0xacab , AbiAddress 0xdeadbeef , AbiAddress 0xbabeface ]
577
+ <> (AbiAddress <$> shrinkIntegral a)
578
+ AbiFunction b -> shrink $ AbiBytes 24 b
579
+
580
+ -- A modification of 'arbitrarySizedBoundedIntegral' quickcheck library
581
+ -- which takes the maxbound explicitly rather than relying on a Bounded instance.
582
+ -- Essentially a mix between three types of generators:
583
+ -- one that strongly prefers values close to 0, one that prefers values close to max
584
+ -- and one that chooses uniformly.
585
+ arbitraryIntegralWithMax :: (Integral a ) => Integer -> Gen a
586
+ arbitraryIntegralWithMax maxbound =
587
+ sized $ \ s ->
588
+ do let mn = 0 :: Int
589
+ mx = maxbound
590
+ bits n | n `quot` 2 == 0 = 0
591
+ | otherwise = 1 + bits (n `quot` 2 )
592
+ k = 2 ^ (s* (bits mn `max` bits mx `max` 40 ) `div` 100 )
593
+ smol <- choose (toInteger mn `max` (- k), toInteger mx `min` k)
594
+ mid <- choose (0 , maxbound)
595
+ elements [fromIntegral smol, fromIntegral mid, fromIntegral (maxbound - (fromIntegral smol))]
0 commit comments